EventEmitter Pattern
Build event-driven applications with EventEmitter. Learn the observer pattern in Node.js.
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.