Node.js Events
Node.js events are a core part of how Node works. Many built-in objects, such as HTTP servers and streams, are event emitters: they announce that something happened, and your listener functions react. You can use the same EventEmitter class to make your own code event-driven.
Creating an EventEmitter
on registers a listener for an event name. emit triggers the event and passes any extra arguments to every listener. Listeners run synchronously, in the order they were added.
import { EventEmitter } from 'node:events';
const shop = new EventEmitter();
shop.on('order', (item, qty) => {
console.log(`New order: ${qty} x ${item}`);
});
shop.emit('order', 'Coffee', 2);
shop.emit('order', 'Tea', 1);New order: 2 x Coffee New order: 1 x Tea
Multiple Listeners and once
once registers a listener that removes itself after the first call.
shop.on('order', () => console.log('Send email receipt'));
shop.once('order', () => console.log('First order of the day!'));
shop.emit('order', 'Juice', 3);
shop.emit('order', 'Water', 1);New order: 3 x Juice Send email receipt First order of the day! New order: 1 x Water Send email receipt
Extending EventEmitter
A common pattern is to build a class that extends EventEmitter, so instances can emit their own events.
import { EventEmitter } from 'node:events';
class Uploader extends EventEmitter {
async upload(file) {
this.emit('start', file);
for (let p = 50; p <= 100; p += 50) {
await new Promise((r) => setTimeout(r, 100));
this.emit('progress', p);
}
this.emit('done', file);
}
}
const up = new Uploader();
up.on('start', (f) => console.log('Uploading', f));
up.on('progress', (p) => console.log(p + '%'));
up.on('done', () => console.log('Finished'));
await up.upload('cv.pdf');Uploading cv.pdf 50% 100% Finished
The error Event
error is special. If an emitter emits error and no listener is attached, Node throws it and your program crashes. Always add an error listener to emitters that can fail.
const job = new EventEmitter();
job.on('error', (err) => console.error('Job failed:', err.message));
job.emit('error', new Error('Disk full'));Job failed: Disk full
Useful EventEmitter Methods
- off(name, fn) — remove a specific listener (alias of removeListener)
- removeAllListeners(name) — remove every listener for an event
- listenerCount(name) — how many listeners are attached
- events.once(emitter, name) — await an event as a promise
- setMaxListeners(n) — change the leak warning threshold (default 10)
Frequently asked questions
What is EventEmitter in Node.js?
A built-in class from node:events that lets objects emit named events and register listener functions for them. Servers, streams and sockets are all EventEmitters.
Are Node.js event listeners asynchronous?
No. emit calls all listeners synchronously in registration order. A listener can start async work itself, but emit does not wait for it.
What does "MaxListenersExceededWarning" mean?
More than 10 listeners were added to one event, which often signals a memory leak, such as adding a listener on every request. Remove listeners you no longer need or raise the limit deliberately.