0.0.2 • Published 2 years ago

@sprs/emitter v0.0.2

Weekly downloads
-
License
MIT
Repository
-
Last release
2 years ago

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 Emitters 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 Emitters.

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 Emitters from this package, and EventTargets 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 Emitters 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]
0.0.2

2 years ago

0.0.1

2 years ago