Events
Asynchronous code often needs to interact with evented code. Using
async/await
this can be quite challenging. Evented code often needs
to be synchronous, because the timing of when to subscribe and
unsubscribe is very critical, otherwise race conditions can occur
where events get missed. Effection has convenient apis to ensure that you never
run into these problems.
Single events
The simplest operation for working with events that Effection provides
is the once()
operation. This operation works with any
EventTarget
and blocks until one of its events
occurs. For example, consider that we wanted to wait for the open
event on a WebSocket
, we could do something like this:
import { main, once } from 'effection';
await main(function*() {
let socket = new WebSocket('ws://localhost:1234');
yield* once(socket, 'open');
console.log('socket is open!');
});
The once
operation returns the argument passed to the event handler. For
example we could use this to grab the code
that the socket closed
with:
import { main, once } from 'effection';
await main(function*() {
let socket = new WebSocket('ws://localhost:1234');
yield* once(socket, 'open');
console.log('socket is open!');
let closeEvent = yield* once(socket, 'close');
console.log('socket closed with code', closeEvent.code);
});
Recurring events
If you've been following the chapter on streams and
subscriptions, you may already have a feeling that it
is not a good idea to repeatedly call once(socket, 'message')
to
grab the messages sent to a WebSocket. The risk here is that we miss
messages if we're not very careful.
Instead we can use on()
. on()
is a very convenient
function which takes an event target and the name of
an event, and returns a Stream of values corresponding to the occurences of
that event.
import { main, once, each } from 'effection';
await main(function*() {
let socket = new WebSocket('ws://localhost:1234');
for (let value of yield* each(on(socket, 'message'))) {
console.log('message:', message.data);
yield* each.next();
}
});