Events & EventEmitter

Node's event-driven core is built on the EventEmitter class, which lets one part of your program emit named events and other parts subscribe with listener functions that run whenever those events fire.

Learn Events & EventEmitter in our free Node.js course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.

Part of the free Node.js course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

By the end of this lesson you'll know how to create an emitter, attach and remove listeners, run a listener only once, build your own class that emits events, and handle the special 'error' event so a stray failure never crashes your program.

What You'll Learn in This Lesson

1️⃣ Creating an Emitter: .on() and .emit()

The pattern has two halves. You subscribe to an event with .on(name, listener) , giving it the name of an event and a function to run. Later, you fire that event with .emit(name, ...args) , and Node runs every listener subscribed to that name, passing along any extra arguments as data.

Read the worked example below — every line is explained — then run it yourself. Notice how the data you pass to .emit() arrives as the listener's argument.

2️⃣ Many Listeners, .once() , and Removing Them

One event can have many listeners — they all run, in the order they were added. Three methods give you fine control:

Trace the output below: the .once() listener fires on the first emit only, and .off() stops tick after the first call.

3️⃣ Your Own Emitter Class & the 'error' Event

Most real Node objects that emit events — servers, streams, sockets — are classes that extend EventEmitter . You can do the same: class Logger extends EventEmitter gives your class .on() , .emit() , and all the rest, so it can announce what it's doing.

One event name is special: 'error' . If an emitter emits 'error' and no listener is registered for it, Node throws and the process exits. Always attach an .on('error', ...) handler to any emitter that might fail.

Your turn. The program below works once you fill in the three blanks marked ___ . Follow the 👉 hints, then run it and compare with the expected output.

No blanks this time — just a brief and an outline to keep you on track. Write it yourself, run it, and check your output against the example in the comments. This is exactly the kind of small program that builds real fluency with events.

📋 Quick Reference — EventEmitter

Practice quiz

Which module provides the EventEmitter class?

  • node:emitter
  • node:events
  • node:stream
  • node:bus

Answer: node:events. EventEmitter is pulled from the built-in node:events module.

What does emitter.on('news', fn) do?

  • Fires the 'news' event
  • Removes a listener for 'news'
  • Subscribes fn to run whenever 'news' is emitted
  • Runs fn exactly once

Answer: Subscribes fn to run whenever 'news' is emitted. .on() subscribes a listener that runs every time the named event is emitted.

Which method fires an event and passes data to every listener?

  • .emit(name, ...args)
  • .on(name, fn)
  • .once(name, fn)
  • .off(name, fn)

Answer: .emit(name, ...args). .emit(name, ...args) fires the event and passes the extra arguments to each listener.

How does .once() differ from .on()?

  • It never runs the listener
  • It runs the listener on every emit, twice as fast
  • It only works for the 'error' event
  • It runs the listener one time, then removes it automatically

Answer: It runs the listener one time, then removes it automatically. .once() runs its listener the first time the event fires and then removes itself.

Are EventEmitter listeners called synchronously or asynchronously?

  • Synchronously, in registration order, before emit returns
  • Asynchronously on the next tick
  • In random order
  • Only after a setTimeout

Answer: Synchronously, in registration order, before emit returns. emit calls every listener right away, in the order they were registered, before it returns.

What happens if you emit 'error' with no listener registered for it?

  • Nothing happens
  • Node throws and the process exits
  • It logs a warning and continues
  • It retries the emit

Answer: Node throws and the process exits. The 'error' event is special: emitting it with no listener throws and crashes the process.

What does MaxListenersExceededWarning usually indicate?

  • The emitter is too fast
  • An event name is misspelled
  • Listeners are being added in a loop and never removed
  • The process is out of memory

Answer: Listeners are being added in a loop and never removed. By default more than 10 listeners on one event warns of a likely leak from listeners never removed.

To remove a listener with .off(), what must you pass?

  • The event name only
  • Any function with the same body
  • A new arrow function
  • The exact same function reference you registered

Answer: The exact same function reference you registered. .off() needs the same function reference, which is why you name listeners you plan to remove.

How do you give your own class .on() and .emit()?

  • class Logger extends EventEmitter
  • class Logger implements EventEmitter
  • new EventEmitter(Logger)
  • EventEmitter.call(Logger)

Answer: class Logger extends EventEmitter. Extending EventEmitter gives your class all the emitter methods so it can announce its own events.

If you call emit('ready') before registering the matching .on('ready', ...), what happens?

  • Node buffers the event and runs the listener later
  • The listener silently never runs
  • It throws an error
  • It runs the listener twice

Answer: The listener silently never runs. emit only calls listeners that already exist, so emitting before subscribing means the listener never runs.