EventEmitter Pattern & Custom Event Architecture0%
EventEmitter Pattern & Custom Event Architecture
Beginner12 min read•Updated: Jul 11, 2026
EventEmitter Pattern & Custom Event Architecture
Node.js is fundamentally an event-driven platform. Much of the Node.js core API (including HTTP servers, streams, and file system watchers) is built around the EventEmitter class located in the built-in node:events module.
1. What is an EventEmitter?
An EventEmitter implements the Observer Design Pattern. Objects (called emitters) emit named events that cause previously registered functions (listeners) to be called synchronously.
JavaScript
import { EventEmitter } from 'node:events';
// Instantiate emitter
const userEmitter = new EventEmitter();
// Register listener for 'userRegistered' event
userEmitter.on('userRegistered', (user) => {
console.log(`[Email Service] Welcome email sent to: ${user.email}`);
});
// Register another independent listener for the SAME event
userEmitter.on('userRegistered', (user) => {
console.log(`[Analytics Service] Logged user registration event for ID: ${user.id}`);
});
// Trigger / Emit the event with payload
userEmitter.emit('userRegistered', { id: 'usr_991', email: 'alex@example.com' });
2. Key Methods of EventEmitter
| Method | Description |
|---|---|
emitter.on(eventName, listener) | Registers a persistent listener that triggers every time the event fires |
emitter.once(eventName, listener) | Registers a one-time listener that automatically removes itself after its first execution |
emitter.emit(eventName, ...args) | Synchronously calls each listener registered for the event with passed arguments |
emitter.removeListener(event, fn) | Unbinds a specific callback from an event |
emitter.setMaxListeners(n) | Increases warning threshold for listener count (default is 10 to prevent memory leaks) |
3. Real-World Architecture: Custom Domain Emitters
In scalable enterprise architectures, custom services inherit from EventEmitter to decouple complex domain processes:
JavaScript
import { EventEmitter } from 'node:events';
class PaymentGateway extends EventEmitter {
async processPayment(transactionId, amount) {
this.emit('paymentStarted', { transactionId, amount });
try {
// Simulate payment processing
await new Promise(resolve => setTimeout(resolve, 500));
this.emit('paymentSuccess', {
transactionId,
amount,
settledAt: new Date()
});
} catch (err) {
this.emit('paymentFailed', { transactionId, error: err.message });
}
}
}
// Consuming the decoupled domain service
const payments = new PaymentGateway();
payments.on('paymentSuccess', (data) => {
console.log('Generating PDF receipt for transaction:', data.transactionId);
});
payments.on('paymentFailed', (data) => {
console.warn('Alerting risk operations team:', data.error);
});
payments.processPayment('tx_88319', 499.00);
Interactive Quiz
Multiple Choice Questions
Question 1
Which core design pattern is implemented by the Node.js
EventEmitter class?Question 2
What happens if you register an event listener using
emitter.once() instead of emitter.on()?Question 3
What is the default maximum number of listeners allowed on an EventEmitter instance before Node.js prints a memory leak warning?
Question 4
How are listeners executed when
emitter.emit('eventName') is invoked?Question 5
What happens if an
error event is emitted on an EventEmitter and no listener is registered for 'error'?Next Lesson
Buffers and Streams: Readable, Writable & Pipeline for Large Files
Continue learning with hands-on practice, examples, and exercises in the upcoming topic.
Related Lessons
Practice Quiz
Test your understanding of this lesson with 5 questions. Each question has one correct answer.