← All tasksJavaScript · Senior
EventEmitter
Write an EventEmitter class with these methods:
on(event, listener) subscribes and returns an unsubscribe function. off(event, listener) unsubscribes. once(event, listener) subscribes for a single call. emit(event, ...args) calls listeners in subscription order and returns true if there were any, false otherwise.
The same listener can be subscribed twice, and then it's called twice. If a listener unsubscribes another one during emit, the current emit still calls everyone who was subscribed when it started.
Ctrl+Enter runs the tests. Tab indents; to leave the editor with the keyboard, press Esc and then Tab. Your code is saved in this browser.
Tests (7)
const e = new EventEmitter(); const f = fn(); e.on('msg', f); e.emit('msg', 1, 2); expect(f).toHaveBeenCalledWith(1, 2);
const e = new EventEmitter(); const a = fn(); const b = fn(); e.on('x', a); e.on('x', b); expect(e.emit('x')).toBe(true); expect(e.emit('y')).toBe(false); expect(a).toHaveBeenCalledTimes(1); expect(b).toHaveBeenCalledTimes(1);
const e = new EventEmitter(); const f = fn(); e.on('x', f); e.off('x', f); e.emit('x'); expect(f).toHaveBeenCalledTimes(0);
const e = new EventEmitter(); const f = fn(); const unsubscribe = e.on('x', f); unsubscribe(); e.emit('x'); expect(f).toHaveBeenCalledTimes(0);
const e = new EventEmitter(); const f = fn(); e.once('x', f); e.emit('x', 'a'); e.emit('x', 'b'); expect(f).toHaveBeenCalledTimes(1); expect(f).toHaveBeenLastCalledWith('a');
const e = new EventEmitter(); const f = fn(); e.on('x', f); e.on('x', f); e.emit('x'); expect(f).toHaveBeenCalledTimes(2);
const e = new EventEmitter(); const calls = []; const second = () => calls.push('second'); const first = () => { calls.push('first'); e.off('x', second); }; e.on('x', first); e.on('x', second); e.emit('x'); e.emit('x'); expect(calls).toEqual(['first', 'second', 'first']);