Peter Seliger
2 min readDec 14, 2023

--

TLDR … The implementation behind what actually is an EventBus approach is error-prone/compromised.

Why re-inventing the wheel? There is already a standardized EventTarget which can be extended or even constructed from. EventTarget is more versatile, since methods like addEventListener or dispatchEvent work within an instance's context. Each instance directly features EventTarget functionality, unlike with the shown EventEmitter class which implements code that forwards to window's addEventListener or dispatchEvent.

Fun fact, window itself implements the EventTarget interface. Thus the introduced EventEmitter class always forwards to EventTarget methods anyhow, but unfortunately exclusively via the window object.

The latter is also the implementation’s 2nd biggest design flaw. Since it dispatches via window, one accidentally could notify a third-party that did subscribe to special (even custom) event-types of window but does not want to be notified about an EventEmitter specific event-type.

In addition to all that the number-one design-flaw is the implementation as an EventEmitter class. This decision shows a profound lack of understanding what instantiation (here not necessary at all because one always forwards via one and the same window object) is all about. If at all, EventEmitter should have been implemented as singleton or single object.

Conclusion … utilize EventTarget directly.

Different libraries provide different implementations and are used for different purposes, but the basic idea is to provide a framework for publishing and subscribing to events.

And regarding the authors quote, the shown implementation behind what actually is an EventBus approach is already in many ways error-prone/compromised. This piece of code is neither a framework nor is it correctly implemented nor is it necessary at all.

A correctly implemented custom event-bus class rather would be close to the following code …

class CustomEventBus {
#eventTarget = new EventTarget;

off(...args) {
return this.#eventTarget.removeEventListener(...args);
}
on(...args) {
return this.#eventTarget.addEventListener(...args);
}
emit(...args) {
return this.#eventTarget.dispatchEvent(...args);
}
}
const eventBus = new CustomEventBus;

eventBus.on('click', evt => console.log({ evt }));

eventBus.emit(new Event('click'));
eventBus.emit(new CustomEvent('click', { detail: { foo: 'FOO' } }));

--

--

No responses yet