promise-events
Version:
A promise-based events emitter
161 lines (103 loc) • 7.05 kB
Markdown
# Promise Events
[](https://travis-ci.org/yanickrochon/promise-events) [](https://coveralls.io/r/yanickrochon/promise-events)
[](https://nodei.co/npm/promise-events/)
An asynchronous event listener for Promise/A+ implementations. This module inherits Node's built-in `EventEmitter` interface, except that selected methods are overridden to return a promise for easy workflow.
In essence, replacing existing code with this emitter should have no impact whatsoever, added that this emitter can work either synchronously or asynchrnously, except that *all* events are emitted asynchronously.
**NOTE:** Modules that expect event emitting to be synchronous should be refactored to wait for the promise resolution instead.
### Usage
```javascript
const EventEmitter = require('promise-events');
var events = new EventEmitter();
// synchronous
events.on('syncEvent', hello => {
console.log(hello);
});
events.emit('syncEvent', 'hello!');
// asynchronous
Promise.all([
events.on('asyncEvent', hello => {
console.log('Handler 1', hello);
return 'Bye!';
}),
events.on('asyncEvent', hello => {
console.log('Handler 2', hello);
})
]).then(() => {
console.log("Event added and any newListener listeners emitted!");
}).then(() => {
events.emit('asyncEvent', 'Hello async!').then(results => {
console.log(results);
// results = [ 'Bye!', undefined ]
});
});
// using async/await
await events.on('asyncEvent', hello => {
console.log('Handler 1', hello);
return 'Bye!';
});
await events.on('asyncEvent', hello => {
console.log('Handler 2', hello);
});
console.log("Event added and any newListener listeners emitted!");
const results = await events.emit('asyncEvent', 'Hello async!');
console.log(results);
// results = [ 'Bye!', undefined ]
```
All listeners are executed using [`Promise.all`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-promise.all).
A call to `events.emit` will always resolve with an array if successful, or a single value--usually an `Error`--otherwise from any listener; the first error thrown, or failure/rejection, will be passed to the rejection callback and all subsequent listeners' resturned values will be ignored.
If necessary, a filter function may be specified for the array of return values using `events.setResultFilter(filter)` (resp. `events.getResultFilter()` and `EventEmitter.defaultResultFilter`, analogous to `EventEmitter.defaultMaxListeners`). Because listeners are called asynchronously, the order of the items in `results` is undefined. Therefore, the amount of listeners, for a given event, and their added order to an emitter is not an indicator of the length of `results` or even the order of values returned when emitting that event. In other words, do not rely on `results` to determine a particular listener's return value.
This module also provides a sugar overload of `.once()` for a Promise-based version of `.once()` which will guarantee to be called *after* all listeners have been emitted, regardless when the listeners were added.
```javascript
// nearly equivalent to events.once('foo', () => console.log('foo!'));
events.once('foo').then(() => console.log('Done!'));
// IMPORTANT : Do not use await on this method unless you know the event will
// be emitted from another asynchronous function!
events.on('foo', () => console.log('foo'));
events.emit('foo');
// => foo
// => Done!
events.emit('foo');
// => foo
```
## API
Most of the implementation is fully compatible with the standard `EventEmitter`. Any extension and overrides are in **bold**, and differences are annotated.
* [Event: 'newListener'](https://nodejs.org/api/events.html#events_event_newlistener)
* [Event: 'removeListener'](https://nodejs.org/api/events.html#events_event_removelistener)
* [EventEmitter.listenerCount(emitter, eventName)](https://nodejs.org/api/events.html#events_eventemitter_listenercount_emitter_eventname) *deprecated*
* [EventEmitter.defaultMaxListeners](https://nodejs.org/api/events.html#events_eventemitter_defaultmaxlisteners)
* **EventEmitter.defaultResultFilter**
* [EventEmitter.errorMonitor](https://nodejs.org/api/events.html#events_eventemitter_errorMonitor)
* [emitter.addListener(eventName, listener)](https://nodejs.org/api/events.html#events_emitter_addlistener_eventname_listener)
Returns a `Promise` resolving when all `newListener` events have been emitted.
* [emitter.emit(eventName[, ...args])](https://nodejs.org/api/events.html#events_emitter_emit_eventname_args)
Returns a `Promise`.
* [emitter.eventNames()](https://nodejs.org/api/events.html#events_emitter_eventnames)
* [emitter.getMaxListeners()](https://nodejs.org/api/events.html#events_emitter_getmaxlisteners)
* **emitter.getResultFilter()**
Return the result filter function.
* [emitter.listenerCount(eventName)](https://nodejs.org/api/events.html#events_emitter_listenercount_eventname)
* [emitter.listeners(eventName)](https://nodejs.org/api/events.html#events_emitter_listeners_eventname)
* **emitter.maxListeners**
Alias for `emitter.getMaxListeners()` and `emitter.setMaxListeners()`.
* [emitter.on(eventName, listener)](https://nodejs.org/api/events.html#events_emitter_on_eventname_listener)
Returns a `Promise` resolving when all `newListener` events have been emitted.
* **emitter.once(eventName)**
Returns a `Promise` that is resolved once *only after* all listeners for the specified event have been called for the given event. (Any `newListener` event will be emitted.)
* [emitter.prependListener(eventName, listener)](https://nodejs.org/api/events.html#events_emitter_prependlistener_eventname_listener)
Returns a `Promise` resolving when all `newListener` events have been emitted.
* **emitter.prependOnceListener(eventName)**
Returns a `Promise` that is resolved once *only before* all listeners for the specified event have been called for the given event. (Any `newListener` event will be emitted.)
* [emitter.removeAllListeners([eventName])](https://nodejs.org/api/events.html#events_emitter_removealllisteners_eventname)
Returns a `Promise` resolving when all `removeListener` events have been emitted.
* [emitter.removeListener(eventName, listener)](https://nodejs.org/api/events.html#events_emitter_removelistener_eventname_listener)
Returns a `Promise` resolving when all `removeListener` events have been emitted.
* **emitter.resultFilter**
Alias for `emitter.getResultFilter()` and `emitter.setResultFilter()`.
* [emitter.setMaxListeners(n)](https://nodejs.org/api/events.html#events_emitter_setmaxlisteners_n)
* **emitter.setResultFilter()**
Set the result filter function.
## Contribution
All contributions welcome! Every PR **must** be accompanied by their associated
unit tests!
## License
MIT