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

```javascript 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

```javascript 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

```javascript 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

```javascript emitter.once('startup', () => { console.log('App started'); });

emitter.emit('startup'); emitter.emit('startup'); ```

**Output:** `App started` (only once)

Error Handling

```javascript 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

```javascript function onData(data) { console.log(data); }

emitter.on('data', onData);

emitter.off('data', onData); ```

Multiple Listeners

```javascript 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