iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

EventEmitter

EventEmitter is Node's pub/sub primitive. Streams, HTTP, child processes — the entire ecosystem extends it. on subscribes; emit fires; off unsubscribes.

Emit, listen, unsubscribe

EXAMPLE
import { EventEmitter } from 'node:events';

class Tracker extends EventEmitter {
    record(event) {
        // do work…
        this.emit('event', { ts: Date.now(), event });
    }
}

const t = new Tracker();

// Subscribe
const handler = e => console.log(e);
t.on('event', handler);

// Subscribe ONCE
t.once('event', e => console.log('first one only', e));

// Emit
t.record('signup');
t.record('login');

// Unsubscribe
t.off('event', handler);

// Inspect
console.log(t.eventNames());          // ['event']
console.log(t.listenerCount('event')); // 0

// Default cap is 10 listeners — bump it intentionally on busy emitters
t.setMaxListeners(50);

// Async listeners — Node won't 'await' you, so handle errors yourself
t.on('event', async e => {
    try { await save(e); }
    catch (err) { t.emit('error', err); }
});

// Best practice: emit an 'error' event; unhandled 'error' crashes the process
t.on('error', err => console.error('tracker:', err));

Why it matters

“MaxListenersExceededWarning” in your logs usually means you added a listener inside a loop without removing it. Always pair on with off — or use once.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
import { EventEmitter } from 'node:events';
const bus = new EventEmitter();
bus.on('boom', n => console.log('boom', n));
bus.emit('boom', 42);
Try it Yourself »

Discussion

Loading…