class EventEmitter { constructor() { this.mapping = new Map(); } subscribe(event, cb) { if (!this.mapping.has(event)) { this.mapping.set(event, new Array()); } this.mapping.get(event).push(cb); return { unsubscribe: () => { this.mapping.set(event, this.mapping.get(event).filter(s => s !== cb)); } }; } emit(event, args = []) { if (!this.mapping.has(event)) { return []; } return this.mapping.get(event).map(cb => cb(...args)); } } /** * const emitter = new EventEmitter(); * * // Subscribe to the onClick event with onClickCallback * function onClickCallback() { return 99 } * const sub = emitter.subscribe('onClick', onClickCallback); * * emitter.emit('onClick'); // [99] * sub.unsubscribe(); // undefined * emitter.emit('onClick'); // [] */