← Усі задачіJavaScript · Senior

EventEmitter

Напишіть клас EventEmitter з методами:

on(event, listener) - підписка; повертає функцію відписки. off(event, listener) - відписка. once(event, listener) - підписка на один виклик. emit(event, ...args) - викликає підписників у порядку підписки й повертає true, якщо вони були, інакше false.

Той самий обробник можна підписати двічі - тоді він викликається двічі. Якщо підписник під час emit відписує іншого, поточний emit однаково викликає всіх, хто був підписаний на його початок.

Тести (7)

  1. const e = new EventEmitter();
    const f = fn();
    e.on('msg', f);
    e.emit('msg', 1, 2);
    expect(f).toHaveBeenCalledWith(1, 2);
  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);
  3. const e = new EventEmitter();
    const f = fn();
    e.on('x', f);
    e.off('x', f);
    e.emit('x');
    expect(f).toHaveBeenCalledTimes(0);
  4. const e = new EventEmitter();
    const f = fn();
    const unsubscribe = e.on('x', f);
    unsubscribe();
    e.emit('x');
    expect(f).toHaveBeenCalledTimes(0);
  5. 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');
  6. const e = new EventEmitter();
    const f = fn();
    e.on('x', f);
    e.on('x', f);
    e.emit('x');
    expect(f).toHaveBeenCalledTimes(2);
  7. 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']);