Table of contents
Hello Devs, i am back with some more knowledge about node and its architecture. In our last article we talked roughly about node's architecture and its queues (Timer queue, IO queue, check queue). we also saw what kind of information these queues have with themselves.
In today's article we'll see how it works and how Event-loop in all helps us to understand the system. Before that we'll talk about 1 more queue and 1 other thing which node provides out of the box that is, process.nextTick()
and microtask queue
.
Micro-Task Queue
This is one of most important queues in nodejs architecture, it contains 2 queues inside.
The 1st queue holds the functions which are passed to
process.nextTick()
, any function/callback that is passed toprocess.nextTick()
is to be executed immediately irrespective of any function that is scheduled before it that is function is executed at next tick. here next tick refers to next iteration of event loop, so at every iteration this queue will be checked and if it holds any function that will be immediately executed.The 2nd queue holds the functions that are delayed by promises, as promises are pending in initial stage as they are rejected or fulfilled the appropriate callbacks are been called, we also have our I/O queue which handles our asynchronous operations (mostly), what nodejs does with this queue is, it stores the function (which comes with promise) with itself and when the appropriate I/O is completed this function is executed.
One very important that node does with its microTask queue is that it checks this queue repeatedly and keeps on executing the function before jumping on next queue, this major change was added after node 11, prior to that microTask queue was not being checked at each iteration.
so now lets try to visualise this complete cycle.
console.log(1);
setTimeout(function foo() {
console.log(‘foo’);
}, 0);
process.nextTick(()=>{console.log('before boo')})
Promise.resolve()
.then(function boo() {
console.log(‘boo’);
});
console.log(2);
// Output:
// 1
// 2
// 'before boo'
// 'boo'
// 'foo'
explanation to above code.
console.log(1) method is called and placed on the call stack and being executed.
SetTimeout is being executed, the console.log(‘foo’) is moved to SetTimeout Web Api, and 0 milliseconds afterward it moves to Macro-Task Queue.
process.nextTick() is being called with a callback function, and the callback function is being moved to Micro-Task queue.
Promise.resolve() is being called, it is being resolved and then .then() method is moved to Micro-Task queue.
console.log(2) method is called and placed on the call stack and being executed.
Event Loop sees that the call-stack is empty, it takes firstly the task from Micro-Task queue which is the process.nextTick() and executes the function later in the next tick (iteration) again the event loop sees that the call stack is empty so it takes the Promise task, puts the console.log(‘boo’) on the call-stack and executes it.
Event Loop sees that the call-stack is empty, then it sees that the Micro-Task is empty, then it takes the next task from the Macro-Task queue which is the SetTimeout task, puts the console.log(‘foo’) on the call-stack and executes it.
with this we some what understand how the node-js event loop works and what are its important parts that are needed to be taken care off.
Conclusion
Node.js is responsible for adding callback functions (attached to an asynchronous operation by JavaScript) to the callback queues. The event loop determines the callback function that would be executed next at every iteration.