В личном кабинете МТС виджеты баланса, тарифа и уведомлений подписываются на общие события: balance:changed, tariff:switched. Напишите класс EventEmitter.
on(event, fn) — подписка, off(event, fn) — отписка, once(event, fn) — обработчик сработает один раз, emit(event, ...args) — вызывает обработчики в порядке подписки и возвращает true, если они были, иначе false.
Если обработчик отписывается во время emit, остальные обработчики этого же события всё равно вызываются. off(event, fn) должен снимать и подписку, сделанную через once(event, fn).
В работе: Шина событий между виджетами страницы, обёртки над WebSocket, аналитика кликов.
Пример 1: порядок подписки
[["on", "balance", "header"], ["on", "balance", "widget"], ["emit", "balance", 350]]
["header(350)", "widget(350)", "emit:true"]
Пример 2: once срабатывает один раз
[["once", "tariff", "toast"], ["emit", "tariff", "Мой безлимит"], ["emit", "tariff", "Мой безлимит"]]
["toast(Мой безлимит)", "emit:true", "emit:false"]
EventEmitter — тест вызывает её сам. Таймеры и Date в тестах ненастоящие: время идёт по команде теста, поэтому setTimeout на 5 секунд проверяется мгновенно. Тестов 7: 2 открыты выше, остальные приходят после старта подхода. Лимит — 2 с на тест.
class EventEmitter { on(event, fn); off(event, fn); once(event, fn); emit(event, ...args) /* → boolean */ }
Источник: обзор транскриптов интервью: EventEmitter — частая задача в МТС, Т‑Банке, Авито. Условие пересказано своими словами.
Ожидаемый ответ не нужен: покажем, что вернула функция.
Здесь появится результат отправки.