@sprs/emitter v0.0.2
Emitter
This package provides a simple, slightly opinionated event emitter with a reduced inferface resembling Node.js's EventEmitter
.
Listener registration is idempotent. Multiple registrations of the same function will not result in multiple invocations of that function.
Use .on
/.off
/.emit
to register/remove listeners and emit events.
Use .xform
to produce a XForm
instance for a single event (see the next section for details on XForm
).
Use the optional events
parameter to Emitter
s constructor to specify known events. The emitter is still allowed to emit any event (no error will be thrown if you emit an event which is not declared in events
). Specifying events
pre-allocates containers for listeners, attaches known property names to an events
property on the Emitter
instance, and provides type annotations for known event names in instance methods.
The emitter
factory wraps the Emitter
class's constructor, and provides a way of creating an Emitter
which does not require the new
keyword.
Example 1: The basics
import { Emitter } from '@sprs/emitter';
const e = new Emitter(['a', 'b', 'c']);
const logIt = value => console.log('a emitted ', value);
e.on('a', logIt);
e.emit('a', 123);
// -> Message logged: 'a emitted 123'
e.off('a', logIt);
e.emit('a', 456);
// -> No message logged
Example 2: Emitter subclass
import { Emitter } from '@sprs/emitter';
class RequestEmitter extends Emitter {
constructor(url, options) {
super(['init', 'response', 'error'])
this.url = url;
this.options = options;
}
init() {
this.emit('init', {
url: this.url,
options: this.options,
});
fetch(this.url, this.options)
.then(response => {
this.emit('response', response);
})
.catch(error => {
this.emit('error', error);
});
}
}
const google = new RequestEmitter('https://www.google.com', { method: 'GET' });
google.on('init', (startValues) => console.log('Request started: ', startValues));
google.on('response', (response) => console.log('Request succeeded: ', response));
google.on('error', (error) => console.log('Request failed: ', error));
google.init();
Example 3: Transforming events
Following is a more complicated example using the fluent xform
API to transform event payloads asynchronously. Most use cases shouldn't require this; if you can, just stick to plain old Emitter
s.
import { Emitter } from '@sprs/emitter';
class RequestEmitter extends Emitter {
...
}
const ddg = new RequestEmitter('https://www.duckduckgo.com', { method: 'GET' });
ddg
.xform({ response: data => data.text() })
.xform({ response: text => text.slice(0, 100) })
.on('response', sliced => console.log('First 100 characters of the Duck Duck Go home page HTML...', sliced))
ddg.init();
XForm
The XForm
class serves as an event transformer. It is constructed from an existing Emitter
and a set of functions to transform event payloads with, and it has the same on
/off
methods as an Emitter
, but it has no emit
method.
XForm
can be used to transform both Emitter
s from this package, and EventTarget
s from the standard browser API.
If a transformer function returns a Promise
, XForm
will wait for that Promise
to resolve, and then will emit the resolved value, rather than immediately emitting the Promise
itself.
The third (optional) parameter to the XForm
constructor provides options. The multiReturn
option requires a transformer function to return an array of values. This allows an XForm
to transform event payloads from Emitter
s which emit multiple values to their events.
The xform
factory function wraps the XForm
class's constructor, and provides a method of creating an XForm
that does not require the new
keyword.
import { Emitter, XForm } from '@sprs/emitter';
const e1 = new Emitter();
const x1 = new XForm(e1, { myEvent: payload => payload.myProperty * 5 });
x1.on('myEvent', console.log);
e1.emit('myEvent', { myProperty: 6 });
// -> '30'
const e2 = new EventTarget();
const x2 = new XForm(e2, { myEvent: event => event.detail.myProperty * 5 });
x2.on('myEvent', console.log);
e2.dispatchEvent(new CustomEvent('myEvent', { detail: { myProperty: 6 } }));
// -> '30'
const emitsMultiple = new Emitter();
const x3 = new XForm(
emitsMultiple,
{ myEvent: (a, b, c) => [a, b * 2, c * 3] },
{ multiReturn: true },
);
x3.on('myEvent', console.log);
emitsMultiple.emit('myEvent', 2, 4, 6);
// -> 2, 8, 18
// Note that this is NOT [2, 8, 18]