Skip to solution
mediumLow-Level Design

What are `EventEmitter`s in Node.js?

847 views
01

Understand the problem

Question presented to candidate: "You register two listeners for the same custom event and emit it once. What order do they fire in, and what happens if you emit an 'error' event with no listener registered for it at all?"

What a strong answer should cover:

  • EventEmitter is Node's built-in publish/subscribe primitive: .on(event, listener) registers a callback, .emit(event, ...args) synchronously invokes every listener registered for that event, in registration order.
  • Multiple listeners on the same event all fire, in the order they were added — verified directly, not just documented, with two listeners producing a strictly ordered result.
  • .once(event, listener) registers a listener that fires at most one time, automatically removing itself after its first invocation — verified across two .emit() calls firing only once.
  • .emit() returns a booleantrue if the event had at least one listener, false if it had none — a real, checkable return value, not merely a side-effecting call.
  • 📌 The critical, special-cased behavior: emitting 'error' on an EventEmitter with no listener registered for it throws synchronously rather than silently doing nothing — this is a deliberate design choice specifically for the 'error' event name, different from every other event, and is why every stream/socket/emitter-based API in Node's ecosystem needs an 'error' listener attached.
  • EventEmitter is the foundation underneath Streams, net.Socket, http.Server, and much of Node's standard library — understanding it deepens understanding of all of those, not just custom application-level events.

Clarifying questions expected:

  • "Is the concern custom application events, or understanding a built-in class (a stream, a socket) that happens to extend EventEmitter?" — the mechanics are identical either way.
  • "Does the codebase register an 'error' listener on every emitter that might emit one?" — the special-cased throw-on-no-listener behavior makes this a real, checkable requirement, not just good practice.

Code / implementation expected: Yes — actually demonstrating listener order, .once(), the boolean return value, and the special 'error'-with-no-listener throw is the concrete, convincing version of this answer.

event emittereventsarchitecturedesign patterns
02

Attempt it yourself

Sketch your approach before reading the solution — that's what interviews test.

Nudge consolestandby

Stuck? Beam a request up — the console returns a conceptual nudge that guides your logic without spoiling the implementation.

03

Study the solution

Target Audience: Engineers preparing for Node.js interviews — assumes very basic callback familiarity, no prior EventEmitter knowledge required. Difficulty: Medium

How to read this doc: Concepts are explained in plain language first, then tagged with 📌 Interview term:. Every behavior below

Solution ready — 2 min read

Classified // press E to declassify

04

Read the code

EventEmitter listener order, once(), the emit() boolean return, and the special 'error'-with-no-listener throw — all verified
const EventEmitter = require("events");
const emitter = new EventEmitter();

const order = [];
emitter.on("greet", () => order.push("listener1"));
emitter.on("greet", () => order.push("listener2"));
emitter.emit("greet");
console.log(order); // [ 'listener1', 'listener2' ] — registration order

let onceCount = 0;
emitter.once("single", () => onceCount++);
emitter.emit("single");
emitter.emit("single");
console.log(onceCount); // 1 — fired only once across two emits

console.log(emitter.emit("nothing-listens")); // false
console.log(emitter.emit("greet"));            // true

try {
  emitter.emit("error", new Error("boom"));
} catch (e) {
  console.log(e.message); // boom — thrown SYNCHRONOUSLY, unlike any other event
}
05

Join the discussion

Discussion (0)

Sign in to join the discussion.

No responses yet. Be the first to share what you think.

Transmission complete // awaiting log

KEEP THE
STREAK ALIVE.

Dossier 63 of 152 decoded in the Node.js track. One more won't hurt.

Back to track