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…