Understanding the event loop and the EventEmitter class is essential to mastering asynchronous programming in Node.js. These two concepts form the backbone of Node.js’s non-blocking, event-driven architecture.
This module explains how the event loop works, what the EventEmitter class does, and how you can use them to write efficient, scalable applications.
Table of Contents
- What Is the Event Loop?
- How Node.js Handles Concurrency
- Phases of the Event Loop
- The Role of
setTimeout
,setImmediate
, andprocess.nextTick
- What Is the EventEmitter Class?
- Creating and Listening to Events
- Using
once()
,off()
, andremoveListener()
- Real-World Use Cases
- Conclusion
1. What Is the Event Loop?
The event loop is a mechanism that handles asynchronous callbacks in Node.js. It allows Node.js to perform non-blocking I/O operations — despite being single-threaded — by offloading operations like file system access and network communication to the system kernel whenever possible.
2. How Node.js Handles Concurrency
Instead of using multiple threads, Node.js uses the event loop and callbacks to manage concurrency. Time-consuming operations are offloaded and their callbacks are pushed onto a queue once completed.
The event loop processes these callbacks one at a time, creating the illusion of multitasking in a single-threaded environment.
3. Phases of the Event Loop
The Node.js event loop has several distinct phases:
- Timers – Executes callbacks scheduled by
setTimeout()
andsetInterval()
. - Pending Callbacks – Executes I/O callbacks deferred to the next loop.
- Idle/Prepare – Internal use only.
- Poll – Retrieves new I/O events; executes their callbacks.
- Check – Executes
setImmediate()
callbacks. - Close Callbacks – Executes callbacks for closed resources.
Each phase has a queue of callbacks to process before moving to the next phase.
4. The Role of setTimeout
, setImmediate
, and process.nextTick
Understanding the differences between these is key:
javascriptCopyEditsetTimeout(() => {
console.log('Timeout');
}, 0);
setImmediate(() => {
console.log('Immediate');
});
process.nextTick(() => {
console.log('Next Tick');
});
Output order:
vbnetCopyEditNext Tick
Timeout
Immediate
process.nextTick()
runs before the next event loop iteration.setTimeout()
executes in the “timers” phase.setImmediate()
executes in the “check” phase.
5. What Is the EventEmitter Class?
Node.js comes with the events
module, which allows you to create and listen for custom events using the EventEmitter
class.
javascriptCopyEditconst EventEmitter = require('events');
const emitter = new EventEmitter();
6. Creating and Listening to Events
You can register event listeners and emit events like this:
javascriptCopyEditconst EventEmitter = require('events');
const emitter = new EventEmitter();
emitter.on('greet', (name) => {
console.log(`Hello, ${name}!`);
});
emitter.emit('greet', 'Alice');
Output:
CopyEditHello, Alice!
7. Using once()
, off()
, and removeListener()
once()
listens for a single occurrence: javascriptCopyEditemitter.once('init', () => console.log('Initialized'));
off()
orremoveListener()
removes an existing listener: javascriptCopyEditconst handler = () => console.log('Running...'); emitter.on('run', handler); emitter.off('run', handler);
8. Real-World Use Cases
- HTTP servers use events like
request
andclose
. - Streams emit
data
,end
, anderror
events. - Custom event-driven architectures in large applications.
- Logging and analytics where you want to emit custom events across modules.
9. Conclusion
The event loop and EventEmitter enable Node.js to handle high-performance, asynchronous applications without blocking execution. By understanding how these features work, you can build scalable applications that handle I/O operations efficiently and react to custom or system events in real time.