Skip to content

Node.js Event Emitter

Node.js operates on an asynchronous, event-driven architecture. This means that many operations in Node.js (like handling network requests, reading files, or interacting with databases) don’t block execution. Instead, they trigger events when they complete or when something significant happens.

The core concept enabling this is the EventEmitter class, found in the built-in events module. Many built-in Node.js objects (like HTTP servers, streams, child processes) inherit from EventEmitter.

The EventEmitter allows objects to emit named events that cause function objects (“listeners”) to be called.

You can use EventEmitter directly to implement the observer pattern in your own code. First, import the class:

const EventEmitter = require('events');

Then, create an instance:

// Create an eventEmitter object
const myEmitter = new EventEmitter();
  • emitter.on(eventName, listener) or emitter.addListener(eventName, listener): Registers a listener function to be called whenever the eventName is emitted. Multiple listeners can be added for the same event.
  • emitter.emit(eventName[, ...args]): Emits the eventName. This synchronously calls each registered listener for this event, in order, passing any supplied args to them.
  • emitter.once(eventName, listener): Registers a listener that will be called at most once for the eventName. The listener is automatically removed after it’s called.
  • emitter.removeListener(eventName, listener) or emitter.off(eventName, listener): Removes the specified listener for the eventName.
  • emitter.removeAllListeners([eventName]): Removes all listeners, or just those for the specified eventName.
  • emitter.listenerCount(eventName): Returns the number of listeners currently registered for the eventName.
  • 'newListener' (eventName, listener): Emitted before a listener is added.
  • 'removeListener' (eventName, listener): Emitted after a listener is removed.
  • 'error' (err): A special event. If an EventEmitter emits an 'error' event and there are no listeners registered for it, Node.js will typically terminate the process with an uncaught exception. It’s crucial to always register an error listener on EventEmitters that might emit errors.

Let’s create a simple example demonstrating the basic usage (eventDemo.js):

const EventEmitter = require('events');
// Create an emitter instance
const myEmitter = new EventEmitter();
// 1. Register a listener for the 'greet' event
const listener1 = (name) => {
console.log(`Listener 1: Hello, ${name}!`);
};
myEmitter.on('greet', listener1);
// 2. Register another listener for the 'greet' event
const listener2 = (name) => {
console.log(`Listener 2: Welcome, ${name}!`);
};
myEmitter.on('greet', listener2);
// 3. Register a one-time listener for 'greet'
myEmitter.once('specialGreet', (message) => {
console.log(`Special Greeting: ${message}`);
});
// Check listener counts
console.log(`Listeners for 'greet': ${myEmitter.listenerCount('greet')}`); // Output: 2
console.log(`Listeners for 'specialGreet': ${myEmitter.listenerCount('specialGreet')}`); // Output: 1
// 4. Emit the 'greet' event with an argument
console.log("\nEmitting 'greet' event...");
myEmitter.emit('greet', 'Alice');
// Both listener1 and listener2 will be called
// 5. Emit the 'specialGreet' event
console.log("\nEmitting 'specialGreet' event...");
myEmitter.emit('specialGreet', 'This happens only once!');
// The listener will be called
console.log(`Listeners for 'specialGreet' after emit: ${myEmitter.listenerCount('specialGreet')}`); // Output: 0
// 6. Remove listener1
console.log("\nRemoving listener 1...");
myEmitter.removeListener('greet', listener1);
console.log(`Listeners for 'greet' after removal: ${myEmitter.listenerCount('greet')}`); // Output: 1
// 7. Emit 'greet' again
console.log("\nEmitting 'greet' event again...");
myEmitter.emit('greet', 'Bob');
// Only listener2 will be called now
// 8. Handling Errors
myEmitter.on('error', (err) => {
console.error('--- An Error Occurred ---');
console.error(err.message);
});
console.log("\nEmitting an 'error' event...");
myEmitter.emit('error', new Error('Something went wrong!'));
// If the error listener wasn't registered, the program would crash here.
console.log('\nProgram Ended.');

Run the script:

$ node eventDemo.js

Expected Output:

Listeners for 'greet': 2
Listeners for 'specialGreet': 1
Emitting 'greet' event...
Listener 1: Hello, Alice!
Listener 2: Welcome, Alice!
Emitting 'specialGreet' event...
Special Greeting: This happens only once!
Listeners for 'specialGreet' after emit: 0
Removing listener 1...
Listeners for 'greet' after removal: 1
Emitting 'greet' event again...
Listener 2: Welcome, Bob!
Emitting an 'error' event...
--- An Error Occurred ---
Something went wrong!
Program Ended.

This example shows how to register listeners (on, once), emit events (emit), check listener counts (listenerCount), remove listeners (removeListener), and handle the special 'error' event.

Understanding EventEmitter is crucial for working effectively with Node.js core modules and many third-party libraries that rely on asynchronous, event-driven patterns.