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