async-await-style synchronization primitive in JavaScript world.
This is like the once helper function in the built-in module events of Node.js but with more powerful utilities.
It is useful to wrap a legacy event-style object to avoid scattered local states.
import EventBarrier from 'event-barrier'
const eb = new EventBarrier
async function foo() {
sendRequest('blah')
await eb.waitFor('response', 5000)
}
// Somewhere else
eb.notify('response', res)import EventBarrier from 'event-barrier'
const eb = new EventBarrier
async function foo() {
try {
for await (const response of eb.asIterator<Response>('response', { timeout: 5000 })) {
// Handle response
}
} catch (err) {
// Asynchronous iteration is aborted
}
}
// Somewhere else
async function handleRequest(requests: Request[]) {
// ...
for (const req of requests.splice(0, 5)) {
// ...
eb.notify('response', res) // Emitted in the same tick
}
for (const req of requests) {
// ...
await someExternalQuery()
eb.notify('response', res) // Emitted in different tick
}
// ...
}Do not use waitFor like this:
async function foo() {
try {
while (true) {
console.log(await eb.waitFor('foo'))
}
} catch (err) {
if (!(err instanceof AbortionError)) throw err
}
}
async function bar() {
eb.notify('foo', 1)
eb.notify('foo', 2)
await nextTick()
eb.notify('foo', 3)
eb.notify('foo', 4)
eb.abort('foo')
}
foo()
bar()The output will be:
1
3
Note that the final waitFor call in foo will not be aborted even if bar has called abort. The reason why 2 and 4 were missed and foo was not aborted is that these events were emitted before the while loop calls waitFor again. More specifically, if you call notify (without specifying a count parameter) multiple times in the same tick, the followings would happen in this tick:
- All pending
waitForcalls will be resolved by the firstnotifycall. - No new
waitForcalls will have a chance to cut in the synchronous sequence ofnotifycalls to get into the queue until next tick.
Hence the ordering of calls/events in the above example is:
- First tick
- First
eb.waitFor('foo')pending eb.notify('foo', 1)- First
eb.waitFor('foo')resolved eb.notify('foo', 2)nextTick- Second tick
- Second
eb.waitFor('foo')pending eb.notify('foo', 3)- Second
eb.waitFor('foo')resolved eb.notify('foo', 4)eb.abort('foo')- Third tick
- Third
eb.waitFor('foo')pending
To read event stream in a async-await fashion, use eb.asIterator, which has an internal queue, as shown in the example.
EventBarrier inherits from events.EventEmitter class, which is a built-in class of Node.js. Therefore, if you want to use EventBarrier in the browser, you need to provide polyfill for events module. For webpack bundler, the polyfill is already included. For rollup bundler, please remember to install the events package:
npm install events --saveIf you are using TypeScript, you may also install typings for the events package:
npm install @types/events --save-dev