Node.js Events
Much of Node.js is built around events: something happens, and the code that is listening reacts.
What is an Event?
An event is a signal that something happened: a request arrived, a file finished loading, or a user placed an order. In Node.js, objects that send events are called event emitters.
Many built-in objects are event emitters, such as HTTP servers ("request" event) and streams ("data" and "end" events). You can also create your own.
Creating an EventEmitter
Example
import { EventEmitter } from "node:events";
const shop = new EventEmitter();
// 1. Listen for an event
shop.on("order", (item, price) => {
console.log(`New order: ${item} for Rs ${price}`);
});
// 2. Send (emit) the event
shop.emit("order", "Zinger Burger", 650);
shop.emit("order", "Fries", 250);New order: Zinger Burger for Rs 650 New order: Fries for Rs 250
on(name, listener)registers a function to run each time the event happensemit(name, ...data)fires the event and passes the data to every listener
Several Listeners
One event can have many listeners. They run in the order they were added.
Example
import { EventEmitter } from "node:events";
const shop = new EventEmitter();
shop.on("order", (item) => console.log("Kitchen: start cooking", item));
shop.on("order", (item) => console.log("Cashier: add", item, "to the bill"));
shop.on("order", (item) => console.log("SMS: your", item, "is being prepared"));
shop.emit("order", "Chicken Tikka");Kitchen: start cooking Chicken Tikka Cashier: add Chicken Tikka to the bill SMS: your Chicken Tikka is being prepared
This is the main benefit of events: the code that emits does not need to know who is listening. You can add new features without changing the old code.
Listening Only Once
once runs the listener only the first time the event happens:
Example
shop.once("open", () => console.log("Shop is open! First customer gets a free drink."));
shop.emit("open");
shop.emit("open");Shop is open! First customer gets a free drink.
Removing Listeners
Example
function logOrder(item) {
console.log("Log:", item);
}
shop.on("order", logOrder);
shop.off("order", logOrder); // removed, will not run againMain EventEmitter Methods
| Method | What it does |
|---|---|
on(event, fn) | Run fn every time the event fires |
once(event, fn) | Run fn only the first time |
emit(event, ...args) | Fire the event with data |
off(event, fn) | Remove a listener |
listenerCount(event) | How many listeners an event has |
removeAllListeners(event) | Remove all listeners for an event |
The error Event
The event name "error" is special. If you emit "error" and no one is listening, Node.js throws the error and your program crashes. Always add an error listener:
Example
shop.on("error", (err) => {
console.error("Problem in the shop:", err.message);
});
shop.emit("error", new Error("Gas cylinder is empty"));Problem in the shop: Gas cylinder is empty
Extending EventEmitter
In real code you often build a class that extends EventEmitter:
Example
import { EventEmitter } from "node:events";
class Classroom extends EventEmitter {
constructor() {
super();
this.students = [];
}
join(name) {
this.students.push(name);
this.emit("joined", name, this.students.length);
}
}
const room = new Classroom();
room.on("joined", (name, total) => console.log(`${name} joined. Total: ${total}`));
room.join("Ali");
room.join("Sara");Ali joined. Total: 1 Sara joined. Total: 2
Listeners run synchronously, one after another, when emit is called. Keep them quick, or start async work inside them.
Exercise
Exercise
What happens if you emit an "error" event and there is no "error" listener?
