Skip to content

Instantly share code, notes, and snippets.

@jeroenransijn
Created February 2, 2016 07:09
Show Gist options
  • Save jeroenransijn/d83c8ec1058dd6f67063 to your computer and use it in GitHub Desktop.
Save jeroenransijn/d83c8ec1058dd6f67063 to your computer and use it in GitHub Desktop.
Events.es2015.js
/**
* Class representing an events interface similar to EventEmitter/Backbone.Events
* @author Jeroen Ransijn [@Jeroen_Ransijn]
* @example
* const events = new Events();
*
* events.on('change', (...args) => { console.log(args); });
* events.trigger('change', 'firstArg', 'secondArg');
* // Returns ['firstArg', 'secondArg']
*
* events.onAll((key, ...args) => { console.log(key, args); });
* events.trigger('randomKey');
* // Returns 'randomKey', ['firstArg', 'secondArg']
*/
export default class Events {
/**
* Create an events interface.
* Sets two properties on this instance
* @property {Map.<Array[Function]>} listeners
* @property {Array.<Function>} globalListeners
*/
constructor () {
this.listeners = new Map();
this.globalListeners = [];
}
/**
* Adds listener(s) to an event by key
* @param {*} key - name of the event
* @param {...Function} listeners - callbacks (...args) to call when the event is triggered
* @return this
*/
on (key, ...listeners) {
if (this.listeners.has(key)) {
const newListeners = this.listeners.get(key);
newListeners.push(...listeners);
this.listeners.set(key, newListeners);
} else {
this.listeners.set(key, [...listeners]);
}
return this;
}
/**
* Adds listener(s) to all events that will ever by triggered
* @param {...Function} listeners - callbacks (key, ...args) to call on all events triggered
* @return this
*/
onAll (...listeners) {
this.globalListeners.push(...listeners);
return this;
}
/**
* Remove listener(s) from an event by key
* Remove all listeners from an event if no listeners are passed
* @param {*} key - name of the events
* @param {...Function} listeners - callbacks to remove from the event
* @return this
*/
off (key, ...listeners) {
if (!this.listeners.has(key)) return this;
if (listeners) {
// Only remove the listeners passed if any are passed
this.listeners.set(key,
this.listeners.get(key).filter((listener) => listeners.find((x) => x !== listener))
);
if (this.listeners.get(key).length === 0) {
// Remove the key if there are no more listeners
this.listeners.delete(key);
}
} else {
this.listeners.delete(key);
}
return this;
}
/**
* Trigger all listener(s) for an events
* @param {*} key - name of the event
* @param {...*} args - arguments to be applied on the listeners
* @return this
*/
trigger (key, ...args) {
this.globalListeners.forEach((listener) => listener(key, ...args));
if (!this.listeners.has(key)) return this;
this.listeners.get(key).forEach((listener) => listener(...args));
return this;
}
}
import { expect } from 'chai';
import Events from './Events';
describe('Events', () => {
const events = new Events();
var stringData;
const stringKey = 'stringKey';
const stringKeyListener = (data) => {
// Set a state we can confirm
stringData = data
};
const symbolKey = Symbol('symbolKey');
const symbolKeyListener = () => {};
const objectKey = { random: 'contents' };
it('creates two instance properties', () => {
expect(events.listeners).to.be.a('map');
expect(events.globalListeners).to.be.a('array');
});
it('can add a listener with a string as a key', () => {
events.on(stringKey, stringKeyListener);
expect(events.listeners.has(stringKey)).to.be.true;
});
it('can add a listener with a symbol as a key', () => {
events.on(symbolKey, symbolKeyListener);
expect(events.listeners.has(symbolKey)).to.be.true;
});
it('can add a listener with an object as a key', () => {
const listener = () => {};
events.on(objectKey, listener);
expect(events.listeners.has(objectKey)).to.be.true;
});
it('can add another listener for a key', () => {
events.on(stringKey, () => {});
expect(events.listeners.get(stringKey)).to.be.a('array');
expect(events.listeners.get(stringKey).length).to.equal(2);
});
it('can add and trigger a global listener with onAll', () => {
var outerState = false;
var outerParam1;
var outerParam2;
const randomParam1Value = 'randomParam1';
const randomParam2Value = 'randomParam2';
const listener = (eventName, ...args) => {
outerState = true;
outerParam1 = args[0];
outerParam2 = args[1];
};
events.onAll(listener);
events.trigger('randomKey', randomParam1Value, randomParam2Value);
expect(outerState).to.be.true;
expect(outerParam1).to.equal(randomParam1Value);
expect(outerParam2).to.equal(randomParam2Value);
});
it('can trigger a listener', () => {
const data = { isHere: true };
events.trigger(stringKey, data);
expect(stringData).to.equal(data);
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment