Skip to content

EventManager

Event-driven application are all around the web. Every (good) JS library or framework provides its method to listen and trigger custom events in order to keep in connection all the modules which it aims to handle.

In Proteins, this features is provided by 3 friendly methods that work with any object source:

  • on: sets up a listener on an object
  • trigger: dispatches a custom event
  • off: destroys a listener

Import the methods

js
// from the Proteins module
import { on, trigger } from '@chialab/proteins';

Listen and trigger events

js
on(window, 'change', (timestamp) => {
    console.log(timestamp);
});

trigger(window, 'change', Date.now());

Remove a specific listener

The simplest way to remove a listener from an object is to use the off method:

js
const callback = (timestamp) => {
    console.log(timestamp);
};

// set up the listener
on(window, 'change', callback);
// dispatch the event
trigger(window, 'change', Date.now());
// remove the listener
off(window, 'change', callback);
// dispatch the event again, but callback is not fired
trigger(window, 'change', Date.now());

Another way is to use the return value of the on method:

js
// set up the listener
let listenerDestroyer = on(window, 'change', (timestamp) => {
    console.log(timestamp);
});
// dispatch the event
trigger(window, 'change', Date.now());
// remove the listener
listenerDestroyer();
// dispatch the event again, but callback is not fired
trigger(window, 'change', Date.now());

Remove multiple (or all) listeners

You can quickly remove bunch of events too, using less parameters for the off function:

js
// remove a single callback
off(window, 'change', callback);
// remove all listeners for the 'change' event
off(window, 'change');
// remove all listeners from window
off(window);

The EmitterMixin and the Emitter class

Proteins does not only provide the event feature, but extends it to classes, in order to add listeners directly to object instances. The built-in Factory.Emitter class provides on, off and trigger methods bound with its prototype:

js
import { Factory } from '@chialab/proteins';

class Shelf extends Emitter {
    constructor() {
        super();
        this.books = [];
    }
    addBook(book) {
        this.books.push(book);
        this.trigger('added');
    }
}

let shelf = new Shelf();

shelf.on('added', () => {
    // render shelf
});

Listen to other objects

Proteins' Emitter prototype has two special methods for listening to other Emitter objects: listen and unlisten.

js
const library = new Emitter();

shelf.listen(library, 'bought', (book) => {
    shelf.addBook(book);
});

library.trigger('bought', { title: 'The Chronicles of Narnia' });

// remove the listener
shelf.unlisten(library, 'bought');

As of the off method, calling unlisten without parameters destroys all listener generated by the scope.

Listen the invisible

If you already have a class (maybe from another library), but you want to add Proteins' events feature, you can use the mixin:

js
import { Factory, mix } from '@chialab/proteins';

const Chart = mix(MyChartClass).with(Factory.EmitterMixin);

let chart = new Chart();

chart.on('data', () => {
    // render chart
});

Released under the MIT License.