Skip to content

Instantly share code, notes, and snippets.

@jagretz
Created May 28, 2018 15:11
Show Gist options
  • Save jagretz/59e5e655a972882003315a2599c019b6 to your computer and use it in GitHub Desktop.
Save jagretz/59e5e655a972882003315a2599c019b6 to your computer and use it in GitHub Desktop.
Custom EventEmitter for created for the purpose of learning and teaching others.
// Example on codepen https://codepen.io/jagretz/pen/aGeMoJ
// If you would like a production version, use complete, tested, performant, and
// well-supported version https://github.com/facebook/emitter
/**
* Subscribe to and control when events are emitted to subscribers.
*/
class EventEmitter {
constructor() {
// k,v store of events to subscribers.
this.events = {};
}
/**
* Register a function (handler) to invoke when the given event (name) is triggered.
* @param {string} name to give the event.
* @param {function} handler to invoke when events are emitted.
* @return {function} #unsubscribe
*/
subscribe(name, handler) {
if (!this.events[name]) this.events[name] = [];
this.events[name].push(handler);
return this.unsubscribe.bind(this, name, handler);
}
/**
* Remove the handler from the list of subscribers.
* If the event has no more subscriptions the event is also removed from the list of events.
*/
unsubscribe(name, handler) {
console.info(`unsubscribing from ${name}`);
this.events[name] = this.events[name].filter(fn => handler !== fn);
if (this.events[name].length <= 0) delete this.events[name];
}
/**
* Identical to #subscribe except that execution only occurs once and immediately unsubscribes.
* This type of subscription is useful in cases when you only need some behavior to occur
* one time.
*/
once(name, handler) {
/* set the "this" context to a variable to pass into the "once" subscription handler.
* this is necessary to invoke the unsubscription function when the handler is invoked.
*/
const self = this;
/* creates a _new_ subscription handler to control both subscription and unsubscription logic. */
function onceHandler(...args) {
self.unsubscribe(name, onceHandler);
handler.apply(self, args);
}
/* subscribe with the _new_ handler. */
this.subscribe(name, onceHandler);
}
/**
* Invokes all subscriber functions subscribed to the event.
* @param {string} name of the event to emit
* @param {*} data provided to each subscriber.
*/
emit(name, data) {
// handler is invoked with .call() to remove the EventEmitter context.
this.events[name] && this.events[name].forEach(handler => handler.call(null, data));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment