Core ModulesIntermediate6 min05 / 11

Events & EventEmitter

Node's event-driven core — emit named events and register listeners with the EventEmitter pattern.

Node is event-driven: much of its API is built on the idea of emitting named events and listening for them. Servers, streams, and many core objects are EventEmitters under the hood. Understanding the pattern unlocks how Node's building blocks talk to each other.

emit and listen
const EventEmitter = require('node:events');

const bus = new EventEmitter();

// register a listener for the 'order' event
bus.on('order', (item) => {
  console.log('New order:', item);
});

// emit the event — every listener runs
bus.emit('order', 'espresso'); // New order: espresso
bus.emit('order', 'latte');    // New order: latte

on(event, listener) subscribes; emit(event, ...args) fires it, calling every registered listener synchronously with the arguments you pass. once(event, listener) runs a listener a single time, then removes it.

#Your own emitters

extend EventEmitter
const EventEmitter = require('node:events');

class Timer extends EventEmitter {
  start() {
    this.emit('tick', Date.now());
  }
}

const t = new Timer();
t.on('tick', (at) => console.log('tick at', at));
t.start();
Common mistake

The special 'error' event

If an EventEmitter emits an 'error' event and no listener is registered for it, Node throws and can crash the process. Always attach an .on('error', ...) listener to emitters that might emit errors (like streams and servers).

Quick check

What happens when you call `bus.emit('order', 'latte')` with two 'order' listeners registered?

Key takeaways

  • Node is event-driven; many core objects (servers, streams) are EventEmitters.
  • `on(event, fn)` subscribes; `emit(event, ...args)` fires all listeners synchronously.
  • `once(event, fn)` runs a listener a single time.
  • Extend EventEmitter to give your own classes emit/on.
  • Always handle the 'error' event — an unhandled one can crash the process.
Practice challenges
Test yourself · earn XP
0/3
Predict the output#1

What does this print?

predict-output
const EventEmitter = require('node:events');
const e = new EventEmitter();
e.on('ping', n => console.log('pong', n));
e.emit('ping', 1);
e.emit('ping', 2);
Fix the bug#2

This emitter crashes the process. What's the safest fix?

fix-bug
const e = new EventEmitter();
e.emit('error', new Error('boom'));
Fill in the blank#3

Complete the line so the listener runs only the first time 'ready' fires.

emitter.('ready', () => console.log('go'));
Your turn
Practice exercise

Create an EventEmitter chat, register a listener for a 'message' event that logs '💬 ' + text, then emit a 'message' with the text 'hello'.

Try it yourself — a starting point to build on:

starter.js
# Write your solution here