Node.js6 min read
EventEmitter Pattern
Build event-driven applications with EventEmitter. Learn the observer pattern in Node.js.
Michael Torres
December 19, 2025
0.0k0
EventEmitter Pattern
EventEmitter is the backbone of Node.js. Almost everything uses events internally.
Basic Usage
const EventEmitter = require('events');
const emitter = new EventEmitter();
emitter.on('userLoggedIn', (username) => {
console.log(`${username} logged in`);
});
emitter.emit('userLoggedIn', 'john_doe');
Output: john_doe logged in
Real Example: Order System
const EventEmitter = require('events');
class OrderSystem extends EventEmitter {
placeOrder(orderId, items) {
console.log(`Processing order ${orderId}`);
this.emit('orderPlaced', { orderId, items });
setTimeout(() => {
this.emit('orderShipped', { orderId });
}, 2000);
}
}
const orders = new OrderSystem();
orders.on('orderPlaced', (data) => {
console.log('Order placed:', data);
});
orders.on('orderShipped', (data) => {
console.log('Order shipped:', data);
});
orders.placeOrder('ORD-123', ['item1', 'item2']);
Output:
Processing order ORD-123
Order placed: { orderId: 'ORD-123', items: ['item1', 'item2'] }
Order shipped: { orderId: 'ORD-123' }
Real Example: File Upload Progress
const EventEmitter = require('events');
const fs = require('fs');
class FileUploader extends EventEmitter {
upload(filePath) {
const stats = fs.statSync(filePath);
const totalSize = stats.size;
let uploaded = 0;
const stream = fs.createReadStream(filePath);
stream.on('data', (chunk) => {
uploaded += chunk.length;
const progress = (uploaded / totalSize) * 100;
this.emit('progress', progress.toFixed(2));
});
stream.on('end', () => {
this.emit('complete');
});
}
}
const uploader = new FileUploader();
uploader.on('progress', (percent) => {
console.log(`Uploaded: ${percent}%`);
});
uploader.on('complete', () => {
console.log('Upload complete!');
});
uploader.upload('large-file.zip');
One-Time Listeners
emitter.once('startup', () => {
console.log('App started');
});
emitter.emit('startup');
emitter.emit('startup');
Output: App started (only once)
Error Handling
emitter.on('error', (err) => {
console.error('Error occurred:', err);
});
emitter.emit('error', new Error('Something went wrong'));
Important: If you don't handle error events, Node.js will crash!
Remove Listeners
function onData(data) {
console.log(data);
}
emitter.on('data', onData);
emitter.off('data', onData);
Multiple Listeners
emitter.on('userLoggedIn', () => {
console.log('Send welcome email');
});
emitter.on('userLoggedIn', () => {
console.log('Update last login time');
});
emitter.on('userLoggedIn', () => {
console.log('Log analytics event');
});
emitter.emit('userLoggedIn');
All three listeners execute when event fires.
Key Takeaway
EventEmitter enables loose coupling between components. Extend EventEmitter for custom classes. Always handle error events. Remove listeners when done to prevent memory leaks.
#Node.js#Events#Patterns#Architecture