Loading lesson path
Concept visual
Start at both ends
The EventEmitter is a module that facilitates communication between objects in Node.js. It's at the core of Node's asynchronous event-driven architecture.
Formula
Many of Node's built - in modules inherit from EventEmitter, including HTTP servers, streams, and more.Formula
// Method 1: Using require const EventEmitter = require('events');// Method 2: ES6 destructuring const { EventEmitter } = require('events');
Creating an EventEmitter const EventEmitter = require('events');
// Create a new EventEmitter instance const myEmitter = new EventEmitter();
// Create a class that extends EventEmitter class MyEmitter extends EventEmitter {
constructor() {
super();
}
}
// Instantiate the extended class const myExtendedEmitter = new MyEmitter();Description addListener(event, listener) Adds a listener to the end of the listeners array for the specified event. Alias for on(). emit(event, [arg1], [arg2], ...) Synchronously calls each of the listeners registered for the event, in the order they were registered, passing the supplied arguments to each. eventNames() Returns an array listing the events for which the emitter has registered listeners. getMaxListeners() Returns the current maximum listener value for the EventEmitter, set by emitter.setMaxListeners(n) or defaults to EventEmitter.defaultMaxListeners. listenerCount(event) Returns the number of listeners listening to the specified event. listeners(event) Returns a copy of the array of listeners for the specified event. off(event, listener) Alias for removeListener(). on(event, listener) Adds a listener to the end of the listeners array for the specified event. once(event, listener)
Formula
Adds a one - time listener for the event that will be removed after it is triggered once.prependListener(event, listener) Adds a listener to the beginning of the listeners array for the specified event. prependOnceListener(event, listener) Adds a one-time listener for the event to the beginning of the listeners array that will be removed after it is triggered once. removeAllListeners([event]) Removes all listeners, or those of the specified event. removeListener(event, listener) Removes the specified listener from the listener array for the specified event. setMaxListeners(n) Sets the maximum number of listeners that can be added to an EventEmitter instance. rawListeners(event) Returns a copy of the array of listeners for the specified event, including any wrappers (like those created by once() ).
EventEmitter.defaultMaxListeners Sets the default maximum number of listeners for all EventEmitter instances. Default is 10. emitter.errorMonitor A static symbol that can be used to install a listener for only monitoring 'error' events. emitter.captureRejections When true, promise rejections are captured and emitted as 'error' events.
Basic EventEmitter Usage const EventEmitter = require('events');
const myEmitter = new EventEmitter();
// Register an event listener myEmitter.on('event', () => {
console.log('An event occurred!');
});
// Emit the event myEmitter.emit('event');
Passing Arguments to Listeners const EventEmitter = require('events');
const myEmitter = new EventEmitter();
// Event with multiple arguments myEmitter.on('status', (code, message) => {
console.log(`Got status: ${code} ${message}`);
});
// Emit with arguments myEmitter.emit('status', 200, 'OK');
One-time Event Listeners const EventEmitter = require('events');
const myEmitter = new EventEmitter();
// Add one-time listener myEmitter.once('onetime', () => {
console.log('This will be called only once');
});
// First emit - will trigger the listener myEmitter.emit('onetime');
// Second emit - won't trigger the listener myEmitter.emit('onetime');
Error Events const EventEmitter = require('events');
const myEmitter = new EventEmitter();
// Error event handler myEmitter.on('error', (err) => {
console.error('Error occurred:', err.message);
});
// Emit an error event myEmitter.emit('error', new Error('Something went wrong'));
// If no 'error' listener is added, Node will throw and crash// Always add an error handler!
Getting Event Names and Listeners const EventEmitter = require('events');
const myEmitter = new EventEmitter();
// Add some listeners myEmitter.on('event1', () => console.log('Event 1'));
myEmitter.on('event2', () => console.log('Event 2'));
myEmitter.on('event2', () => console.log('Event 2 again'));
// Get all event names console.log('Event names:', myEmitter.eventNames());
// Get listeners for a specific event console.log('Listeners for event2:', myEmitter.listeners('event2'));
// Count listeners console.log('Listener count for event2:', myEmitter.listenerCount('event2'));
Removing Listeners const EventEmitter = require('events');
const myEmitter = new EventEmitter();
// Define listener function (needed for removal) function listener1() {
console.log('Listener 1 executed');
}
function listener2() {
console.log('Listener 2 executed');
}
// Add listeners myEmitter.on('event', listener1);
myEmitter.on('event', listener2);
console.log('Listeners before removal:', myEmitter.listenerCount('event'));
// Remove a specific listener myEmitter.removeListener('event', listener1);
// or using the alias: myEmitter.off('event', listener1);
console.log('Listeners after removal:', myEmitter.listenerCount('event'));
// Remove all listeners for an event myEmitter.removeAllListeners('event');
console.log('Listeners after removeAll:', myEmitter.listenerCount('event'));
Setting Maximum Listeners const EventEmitter = require('events');// Set the default max listeners for all EventEmitter instances
EventEmitter.defaultMaxListeners = 15;
const myEmitter = new EventEmitter();
// Set max listeners for a specific instance myEmitter.setMaxListeners(20);
console.log('Default max listeners:', EventEmitter.defaultMaxListeners);
console.log('myEmitter max listeners:', myEmitter.getMaxListeners());// Adding more than maxListeners will trigger a warning // The warning helps identify potential memory leaks
Order of Listeners const EventEmitter = require('events');
const myEmitter = new EventEmitter();
// Default behavior: listeners execute in order they were added myEmitter.on('event', () => console.log('First listener'));
myEmitter.on('event', () => console.log('Second listener'));
// Prepend a listener (it will execute first)
myEmitter.prependListener('event', () => console.log('Prepended listener'));
// One-time prepended listener myEmitter.prependOnceListener('event', () => console.log('Prepended once listener'));
// Emit the event myEmitter.emit('event');// Output will be: // Prepended once listener // Prepended listener // First listener // Second listener
A common pattern in Node.js is to create a class that extends EventEmitter, adding custom functionality:
const EventEmitter = require('events');
// Custom class that extends EventEmitter class MyApp extends EventEmitter {
constructor() {
super();
this.name = 'MyApp';
}
process(data) {
// Do some processing console.log(`Processing data: ${data}`);
// Emit events based on processing results if (data.length > 10) {
this.emit('large-data', data);
} else {
this.emit('small-data', data);
}
// Emit completion event this.emit('processed', data);
}
}
// Create an instance const app = new MyApp();
// Register event listeners app.on('large-data', (data) => {
console.log(`Large data detected: ${data.length} bytes`);
});
app.on('small-data', (data) => {
console.log(`Small data detected: ${data.length} bytes`);
});
app.on('processed', (data) => {
console.log('Processing completed');
});
// Use the app app.process('Hello');
app.process('Hello, this is a longer string of data');Asynchronous vs. Synchronous EventEmitter calls all listeners synchronously in the order they were registered. Important for maintaining the expected execution order:
const EventEmitter = require('events');
const myEmitter = new EventEmitter();
// Register listener myEmitter.on('event', () => {
console.log('Listener executed');
});
// Emit event console.log('Before emit');
myEmitter.emit('event');
console.log('After emit');// Output: // Before emit // Listener executed // After emit To run listeners asynchronously, you can use setImmediate() or process.nextTick():
const EventEmitter = require('events');
const myEmitter = new EventEmitter();
// Register async listener using setImmediate myEmitter.on('async-event', () => {
setImmediate(() => {
console.log('Async listener executed');
});
});
console.log('Before emit');
myEmitter.emit('async-event');
console.log('After emit');// Output: // Before emit // After emit // Async listener executed
EventEmitter in modern Node.js versions can handle Promises and capture rejections:
const EventEmitter = require('events');
// Enable capture rejections (Node.js 12.16.0+)
const myEmitter = new EventEmitter({ captureRejections: true });// OR set it globally
// EventEmitter.captureRejections = true;
// Event handler that returns a Promise myEmitter.on('async-operation', async () => {
// This rejected promise will be captured and converted to an 'error' event throw new Error('Async operation failed');
});
// Error handler myEmitter.on('error', (err) => {
console.error('Caught error:', err.message);
});
// Trigger the event myEmitter.emit('async-operation');EventEmitter powers many Node.js core modules. Here's how an HTTP server uses events:
const http = require('http');
// HTTP Server is an EventEmitter const server = http.createServer();
// Listen for 'request' events server.on('request', (request, response) => {
console.log(`Received ${request.method} request for ${request.url}`);
response.writeHead(200, { 'Content-Type': 'text/plain' });
response.end('Hello World\n');
});
// Listen for 'connection' events server.on('connection', (socket) => {
console.log('New client connection from', socket.remoteAddress);
});
// Listen for 'close' event server.on('close', () => {
console.log('Server closed');
});
// Listen on port 8080 server.listen(8080, () => {
console.log('Server listening on port 8080');
});// Later, we can close the server
// server.close();const EventEmitter = require('events');
const myEmitter = new EventEmitter();
// Always add error handlers myEmitter.on('error', (err) => {
console.error('Error occurred:', err);// Handle the error appropriately
});2. Cleanup Listeners to Prevent Memory Leaks const EventEmitter = require('events');
const myEmitter = new EventEmitter();
function setupHandler() {
const handler = () => console.log('Event handled');
// Add the handler myEmitter.on('some-event', handler);
// Return a cleanup function return function cleanup() {
myEmitter.removeListener('some-event', handler);
};
}
// Set up a handler const cleanup = setupHandler();
// Later, when no longer needed cleanup();// BAD - Cannot remove this listener later emitter.on('event', () => console.log('Anonymous function'));
// GOOD - Can be removed by reference function namedHandler() {
console.log('Named function');
}
emitter.on('event', namedHandler);
// Later emitter.removeListener('event', namedHandler);