Implement event-dispatcher
Event Dispatcher implemented by objects that can receive events and may have listeners for them.
Question
Implement an Event dispatcher which has a way to add listener, remove listeners and dispatch events
EventDispatcher.addEventListener()EventDispatcher.removeEventListener()EventDispatcher.dispatch(Event)
- Create
EventDispatcher
class with 3 empty methods:
addEventListenerremoveEventListenerdispatch
- Add
_listeners
store as object inEventDispatcher
:
constructor() {this._listeners = {};}
- Implement
addEventListener
that stores listener to_listeners
:
const ed = new EventDispather();ed.addEventListener('event', () => {});
- Also we need to implement
removeEventListener
to delete some listeners:
const ed = new EventDispather();ee.removeEventListener('event', () => {});
- Last one is
dispatch()
:
/*We can create native events in browser like this:*/const event = new CustomEvent('my-event');const ed = new EventDispather();/* dispatch this event */ed.addEventListener('event', () => {/* should handle event below */});ed.dispatchEvent(event);
Solution
class EventDispatcher {constructor() {// listeners storethis._listeners = {};}addEventListener(type, listener) {// validationif (this._listeners[type] === undefined) {this._listeners[type] = [];}// if event not provided push into listeners arrayif (this._listeners[type].indexOf(listener) === -1) {this._listeners[type].push(listener);}}removeEventListener(type, listener) {// validationif (this._listeners === undefined || this._listeners[type] === undefined) return;// found listener candidate to deleteconst index = this._listeners[type].indexOf(listener);// if founded deleteif (index !== -1) {this._listeners[type].splice(index, 1);}}dispatchEvent(event) {// validationif (this._listeners === undefined || this._listeners[event.type] === undefined) return;// create a copy to avoid race conditionconst eventListenersCopy = this._listeners[event.type].slice(0);// bind target contextevent.target = this;// move through listeners array and dispatchfor (let i = 0; i < eventListenersCopy.length; i++){eventListenersCopy[i].call(this, event);}}}// example using belowconst ed = new EventDispatcher();// DO NOT USE ON PRODUCTION. ONLY FOR EXAMPLEconst event = {target: null,type: 'my-event'};const listener = () => {console.log('handled!');};ed.addEventListener('my-event', listener);// should be handleded.dispatchEvent(event);ed.removeEventListener('my-event', listener);// should not be handleded.dispatchEvent(event);
Caveat
Be careful with too many listeners. It can cause memory leaks. Remove them when no longer needed.