Node.js Events — Complete Guide to EventEmitter and Event-Driven Architecture
In this tutorial, you will learn about Node.js Events. We cover key concepts, practical examples, and best practices to help you master this topic.
Node.js EventEmitter implements the Observer Patternver" >}} pattern, enabling objects to emit named events that trigger registered listener functions for asynchronous communication.
What You'll Learn
By the end of this tutorial, you'll use EventEmitter to create and handle custom events, manage listener lifecycles, extend EventEmitter in classes, and build event-driven architectures.
Why Events Matter
Node.js is fundamentally event-driven. HTTP servers, streams, and file operations all use events internally. Understanding EventEmitter helps you build decoupled, scalable systems.
Real-World Use
A chat server emits events when users connect, send messages, or disconnect. Different handlers Process each event independently, making the system modular and testable.
Events Learning Path
flowchart LR
A[Buffers] --> B[Events]
B --> C[Error Handling]
C --> D[Debugging]
D --> E[Express.js]
A --> F{You Are Here}
style F fill:#f90,color:#fff
Basic EventEmitter Usage
import { EventEmitter } from "node:events";
const emitter = new EventEmitter();
emitter.on("greet", (name) => {
console.log(`Hello, ${name}!`);
});
emitter.emit("greet", "Alice"); // Hello, Alice!
Event Arguments
Events can pass multiple arguments to listeners.
emitter.on("data", (status, message, code) => {
console.log(`[${status}] ${message} (${code})`);
});
emitter.emit("data", "OK", "Request successful", 200);
// Output: [OK] Request successful (200)
Once Listeners
Listeners registered with .once() fire at most one time.
emitter.once("connection", () => {
console.log("First connection established");
});
emitter.emit("connection"); // Fires
emitter.emit("connection"); // Does nothing
Error Events
If an EventEmitter emits an 'error' event without a listener, Node.js throws the error and crashes the process.
emitter.on("error", (err) => {
console.error("Caught error:", err.message);
});
emitter.emit("error", new Error("Something went wrong"));
// Caught error: Something went wrong
Managing Listeners
const listener = () => console.log("Event fired");
emitter.on("update", listener);
console.log(emitter.listenerCount("update")); // 1
console.log(emitter.eventNames()); // ['update', ...]
emitter.removeListener("update", listener);
emitter.removeAllListeners("update");
Extending EventEmitter
class Logger extends EventEmitter {
log(level, message) {
const entry = `[${level}] ${message}`;
this.emit("log", entry);
if (level === "ERROR") {
this.emit("error", new Error(message));
}
}
}
const logger = new Logger();
logger.on("log", (entry) => console.log(entry));
logger.on("error", (err) => console.error("Alert:", err.message));
logger.log("ERROR", "Connection refused");
Max Listeners Warning
By default, EventEmitter warns if more than 10 listeners are added to the same event. This prevents memory leaks.
emitter.setMaxListeners(20); // Increase limit
Common Mistakes
1. Forgetting to Handle 'error' Events
An unhandled 'error' event crashes the process. Always attach an error listener to custom EventEmitters.
2. Adding Listeners Inside Loops
This creates multiple listeners unintentionally. Move listener registration outside loops.
3. Memory Leaks from Forgotten Listeners
Objects with listeners attached cannot be garbage collected. Remove listeners when no longer needed.
4. Using Arrow Functions When You Need to Remove Listeners
Arrow functions cannot be referenced for removal. Store the reference if you need to remove it later.
5. Emitting Events Before Listeners Are Registered
Events emitted before .on() calls are lost. Emit events only after listeners are attached.
Practice Questions
1. What is the difference between on and once?
on fires the listener every time the event is emitted. once fires the listener at most one time and then removes it.
2. What happens if an EventEmitter emits 'error' with no listener?
Node.js throws the error and crashes the process (if unhandled). Always register an error listener.
3. How do you remove a specific listener?
Call emitter.removeListener(event, listener) or emitter.off(event, listener) with a reference to the same function.
4. What is the default max listeners per event?
- Exceeding this logs a warning. Use
setMaxListeners()to increase.
5. Challenge: Create a task queue that emits events when tasks are added, processed, and completed.
class TaskQueue extends EventEmitter {
constructor() { super(); this.tasks = []; }
add(task) {
this.tasks.push(task);
this.emit("added", task);
}
process() {
while (this.tasks.length) {
const task = this.tasks.shift();
this.emit("processing", task);
this.emit("completed", task);
}
}
}
const queue = new TaskQueue();
queue.on("completed", (task) => console.log(`Done: ${task}`));
queue.add("Send email");
queue.add("Generate report");
queue.process();
FAQ
Mini Project: Download Manager
Build a download manager that emits events for progress updates, completion, and errors.
import { EventEmitter } from "node:events";
import fs from "node:fs";
import https from "node:https";
class DownloadManager extends EventEmitter {
download(url, dest) {
this.emit("start", url);
const file = fs.createWriteStream(dest);
https.get(url, (response) => {
const total = parseInt(response.headers["content-length"], 10);
let downloaded = 0;
response.on("data", (chunk) => {
downloaded += chunk.length;
this.emit("progress", { url, downloaded, total, percent: ((downloaded / total) * 100).toFixed(1) });
});
response.pipe(file);
file.on("finish", () => this.emit("complete", url));
}).on("error", (err) => this.emit("error", { url, error: err.message }));
}
}
const dm = new DownloadManager();
dm.on("progress", (p) => process.stdout.write(`\r${p.url}: ${p.percent}%`));
dm.on("complete", (url) => console.log(`\nDownloaded: ${url}`));
dm.download("https://nodejs.org/dist/v22.0.0/node-v22.0.0-linux-x64.tar.gz", "node.tar.gz");
What's Next
Node.js Child Process Node.js Error Handling Express.js
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro