Working with Events

1. Creating Event Emitters

Example

import { EventEmitter } from "node:events";
class Bus extends EventEmitter {}
const bus = new Bus();

2. Registering Event Listeners

MethodDescription
on(event, fn)Add listener
addListenerAlias of on
off(event, fn)Remove listener
removeAllListeners(event?)Clear

3. Using Once Listeners

Example

bus.once("ready", () => console.log("first time only"));
import { once } from "node:events";
const [data] = await once(bus, "data"); // promise-based

4. Emitting Events

APIReturns
emit(event, ...args)true if any listeners

5. Removing Listeners

PatternUse
bus.off("x", fn)Remove a specific fn
Save reference to anon fnSo you can remove later

6. Prepending Listeners (prependListener)

MethodEffect
prependListenerInsert at front of list
prependOnceListenerFront + once

7. Getting Listener Count (listenerCount)

APIReturns
bus.listenerCount("x")Number
bus.listeners("x")Array of fns
bus.eventNames()All registered names

8. Setting Max Listeners (setMaxListeners)

APIDefault
setMaxListeners(n)10
EventEmitter.defaultMaxListenersGlobal default
Note: Exceeding triggers a "MaxListenersExceededWarning" (possible memory leak).

9. Handling Error Events

Warning: Unhandled "error" events crash the process.

Example

bus.on("error", (err) => logger.error(err));
bus.emit("error", new Error("boom"));

10. Using Async Iterators on Events

Example

import { on } from "node:events";
for await (const [msg] of on(bus, "message")) {
  if (msg === "stop") break;
}

11. Creating Custom Event Emitters

Example: Typed emitter (TS)

type Events = { ready: []; data: [Buffer]; error: [Error] };
class Typed extends EventEmitter {
  on<K extends keyof Events>(e: K, fn: (...a: Events[K]) => void) { return super.on(e, fn as any); }
  emit<K extends keyof Events>(e: K, ...a: Events[K]) { return super.emit(e, ...a); }
}
Class VariantDetail
EventEmitterAsyncResourceIntegrates with async hooks
captureRejections: trueAuto-emit "error" on async listener rejection