The Ultimate Guide to the Event Loop in Node.js
When learning something new, understanding its fundamentals at a root level is extremely important. In this guide, we’ll explore what the event loop is and how it works behind the scenes in Node.js.
We’ll cover:
What is an Event Loop?
The event loop is the mechanism that allows Node.js to perform non-blocking I/O operations using a single main thread. It works basically by offloading the operations such as file system, crypto, and timers, etc, to libuv.
How it works
When Node.js executes code, it processes both synchronous and asynchronous operations.
Libuv manages these operations and sends its callback functions to different callback queues.
Meanwhile, the event loop continuously checks whether the V8 call stack is empty. Once the call stack becomes empty, the event loop pulls pending callbacks (based on priority and phase) and pushes them onto the call stack for execution.
Event Loop Phases
The event loop is primarily divided into four important phases:
What happens in each phase?
The Inner Cycle (Microtasks)
Apart from these main phases, there is also a microtask queue that runs:
These microtasks run:
Please review the diagram below to better understand the concepts discussed above.
Recommended by LinkedIn
Code Example: Execution Flow
Now we will see the code examples to understand how the operations are executed.
const a = 100;
setImmediate(()=> console.log("SetImmediate"));
fs.readFile("file.text","utf8", (err, data) => console.log("File ",data));
setTimeout(()=> console.log("Timeout"), 0);
Promise.resolve().then(()=> console.log("Promise"));
process.nextTick(()=> console.log("NextTick"));
function printA() {
console.log(a);
}
printA()
console.log("Last line of code")
Step 1: Execute synchronous code first
The V8 engine runs synchronous lines immediately:
Output so far:
100
Last line of code
Step 2: Microtasks (process.nextTick & Promise)
Once synchronous execution finishes, the microtask queue runs:
Output now becomes:
100
Last line of code
NextTick
Promise
Step 3: Timers Phase
setTimeout(..., 0) executes next:
Output:
100
Last line of code
NextTick
Promise
Timeout
Step 4: Check Phase
setImmediate() is executed:
100
Last line of code
NextTick
Promise
Timeout
SetImmediate
Step 5: Poll Phase
Finally, once the event loop enters the Poll phase again, the fs.readFile callback runs:
Final output:
100
Last line of code
NextTick
Promise
Timeout
SetImmediate
File Hello World
The event loop may seem complex at first, but once you break it down into phases and understand how callbacks are scheduled, everything starts to make sense. By learning how Node.js handles asynchronous operations, you can write cleaner, faster, and more reliable code. Keep experimenting with examples, and you’ll quickly become comfortable with how the event loop affects your application’s behavior.
I hope this article helped you understand the concept of the Node.js event loop, and you found it informative.
Happy coding! 🚀
Hi Sahil Pate nice article! One question about synchronous tasks: if I have an asynchronous task like an API call and a console.log after that, according to your article, the API call goes to "another queue" and Node processes the console.log. After all the phases, the event loop checks if the API call is finished and then returns the response and executes the console.log. Is that right?"