Code Snippets
/

Tiny Pub/Sub Event Bus

Tiny Pub/Sub Event Bus

When two parts of your app need to talk without a direct reference (a Zustand store telling the toaster, a service worker pushing to the UI), a tiny pub/sub bus is often cleaner than threading callbacks. This snippet builds a minimal `on/off/emit` bus, adds a `once` shorthand, and shows the typed channels pattern that scales to a real codebase. Drop it in next to your state library.

JavaScript
Medium
3 snippets
observer-pattern
event-driven
utility
code-template

942 views

18

function createBus() {
    const listeners = new Map();
    function on(event, fn) {
        if (!listeners.has(event)) listeners.set(event, new Set());
        listeners.get(event).add(fn);
        return () => listeners.get(event).delete(fn);
    }
    function off(event, fn) {
        const set = listeners.get(event);
        if (set) set.delete(fn);
    }
    function emit(event, payload) {
        const set = listeners.get(event);
        if (!set) return;
        for (const fn of [...set]) fn(payload);
    }
    return { on, off, emit };
}

const bus = createBus();
bus.on('user:login', (u) => console.log('hi', u.name));
bus.emit('user:login', { name: 'Ada' });

Storing listeners in a Map<event, Set<handler>> gives O(1) add/remove and prevents duplicate registrations of the same function. Returning an unsubscribe function from on is a small ergonomic win that pairs well with React effects (return unsubscribe) and removes the need for callers to keep a reference to the original handler. Iterating over [...set] in emit snapshots the listener list so a handler that calls off mid-dispatch does not skip later listeners. Use this when you need decoupled cross-tree messaging without pulling in a dependency.