Card 05/ 09
Observer in the Wild: Node's EventEmitter
on() subscribes, emit() notifies, and the browser's addEventListener is the same shape.
Node's EventEmitter, from the built-in events module, is a subject that any object can be or extend. Its on method attaches a listener for a named event, off detaches it, and emit calls every listener for that event with the arguments given. This card subscribes two listeners to an order event, detaches one, and emits again.
import { EventEmitter } from "events";
const orders = new EventEmitter();
const sendEmail = (id: number) => console.log(`email for order ${id}`);
const updateStock = (id: number) => console.log(`stock updated for order ${id}`);
orders.on("placed", sendEmail);
orders.on("placed", updateStock);
console.log("listeners:", orders.listenerCount("placed"));
orders.emit("placed", 1001);
orders.off("placed", sendEmail);
console.log("listeners:", orders.listenerCount("placed"));
orders.emit("placed", 1002);listeners: 2
email for order 1001
stock updated for order 1001
listeners: 1
stock updated for order 1002The first emit reaches both listeners in the order they subscribed, and after off the second reaches only the stock update. The listing was compiled with TypeScript and run on Node 22, with a short type declaration for the events module standing in for Node's published types.
The participants map directly. The emitter is the subject, on and off are attach and detach, emit is notify, and each listener function is an observer. One difference from the template is the event name: one emitter can be a subject for many events, keeping a separate list for each.
A browser has the same shape on every element. button.addEventListener("click", handler) attaches an observer, removeEventListener detaches it, and a click notifies every handler: the same pattern under different names.
← → move through sections and cards