Custom Events in JavaScript: Building a Simple Pub/Sub System

Beyond built-in DOM events like click, JavaScript lets you define and dispatch your own custom events — a clean way to decouple different parts of an application without them directly calling each other.

// Dispatching a custom event with data
const event = new CustomEvent('cart:updated', {
    detail: { itemCount: 3, total: 59.97 },
    bubbles: true,
});
document.dispatchEvent(event);

// Listening for it anywhere else in the app - no direct coupling needed
document.addEventListener('cart:updated', (e) => {
    console.log(<code>Cart now has ${e.detail.itemCount} items</code>);
    updateCartBadge(e.detail.itemCount);
});

A Simple Pub/Sub System Built on This

class EventBus extends EventTarget {
    emit(name, detail) {
        this.dispatchEvent(new CustomEvent(name, { detail }));
    }
    on(name, handler) {
        this.addEventListener(name, handler);
    }
}

const bus = new EventBus();
bus.on('user:login', (e) => console.log('Logged in:', e.detail));
bus.emit('user:login', { userId: 42 });

This pattern lets a cart component, a notification badge, and an analytics tracker all react to the same “cart updated” moment without any of them needing a direct reference to each other — genuinely useful for decoupling unrelated parts of a larger application.