TaskMake const bus = new EventTarget(). Subscribe to 'order-placed' with a handler that logs 'received: ' + e.detail.id. Dispatch new CustomEvent('order-placed', {detail: {id: 42}}). Then removeEventListener and dispatch again — second one should not log anything new.
EventTarget — your own event bus
125 XP9 min
Theory
The same API DOM elements expose
Every DOM element uses addEventListener / dispatchEvent because they extend EventTarget. You can use EventTarget directly to build a tiny pub/sub bus — no library needed.
const bus = new EventTarget();
bus.addEventListener("user-login", (e) => {
console.log("welcome", e.detail.name);
});
bus.dispatchEvent(new CustomEvent("user-login", { detail: { name: "Anna" } }));
// "welcome Anna"CustomEvent
new CustomEvent(name, { detail }) lets you attach an arbitrary payload at event.detail. That's how libraries thread structured data through DOM events.
Why this pattern wins
- Same shape as DOM events — anyone who knows the browser knows the API.
- Composable — multiple listeners, removeEventListener, AbortSignal for cleanup.
- Zero dependencies.
removeEventListener
To stop listening, pass the SAME function reference:
const handler = (e) => console.log(e.detail);
bus.addEventListener("ping", handler);
bus.removeEventListener("ping", handler);Or use AbortSignal: bus.addEventListener("ping", handler, { signal: ctrl.signal }) — ctrl.abort() removes the listener.
🔒
Sign up to start coding
Theory is open to everyone. The interactive editor, live preview, and check are unlocked with a 7-day free trial — card required, cancel anytime.
Sign up — free trial →First 10 lessons in each track are free. No card needed for those.