In the last article, we have learnt about how JavaScript execution works. But that is not the complete flow. We have not taken a few properties into account and that’s why in this article we will cover all of them in detail and in-depth.
Let’s start.
Understanding the problem statement
Let’s have a look at the below code: –
//Code 1
console.log("start");
function func1(){
console.log("inside function")
}
func1();
console.log("end");
//Code 2
console.log("start");
setTimeout(function(){
console.log("inside function")
}, 2000);
console.log("end");
The way how the above codes will execute in java scipt in completely different.
Since JavaScript is a single-threaded language, the execution will start from top to bottom.
- In code 1 , the execution will start from top to bottom and the output will be printed as below
- In code 2 , since we have settimeout i.e part of web API, the flow of execution changes and hence the o/p is as below
Code 1 output
----------------
start
inside function
end
Code 1 output
----------------
start
end
inside function
Adding event loop to the execution flow
- Step 1 – As soon as js engine finds the script tag, it creates a global execution context inside the call stack.
- Step 2 – It first encounters the log statement and prints the output “start“
- Step 3 – It finds the function and creates a stack of functional execution context above the global execution context. Now in the execution phase, the setimeput API of the browser is pushed to WEB API’s memory. The callback of set timeout is added to WEB API’s, and a time of 2sec is attached to it.
- Step 4 – The function execution context is now popped out and since js engine is a single-threaded, the execution moves forward, and the next log statement is printed i.e “end“
- Step 5 – Now once the 2 sec timer is completed, the callback function is added to task queue i.e macrotask queue to be sepecfic, where it will be waiting in a queue for the call stack to be empty. The task under queue is executed as first come first serve basis.
- Step 6 – Now comes the job of event loop. The main job of event loop is to check if call stack is empty, and once its empty, it will push the tasks in task queue to call stack for execution.
- Step 7 – Finally the callback function of setTimeout pushed to call stack and executed.
- Step 8 – Call stack becomes empty , and the executed end.
Now go ahead and drink some water🥛
Definition of all the jargons
CallStack
Callback keeps track of the function calls , managing their execution and maintaining the program state.
Web API’s
Web APi's are the browser provied API to extend the functionality of a web browser. For eg - http/https, dom api , fetch api , event listeners api , etc .
Task Queue/Callback Queue
Task comes under task queue are typlically input events , timer events, and other event from web api's
Microtask Queue
Task comes under microtask queue are ususally associates with the promises and it has hight priority than macrotask queue. Example - process.nextTick, Promises, queueMicrotask, MutationObserver
Macrotask Queue
This queue only executes once all the macro task queue becomes emepty. It has lowest priority. Example - setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O, UI Rendering
Priority of the task queue
Let’s say we have a setTimeout , promises , console log and event listeners are in the call stack.
Now the question is which will be executed first.
- console.log will be executed first , as it directly executes on the call stack.
- Secondly, since promise comes under microtask queue which has the higher priority.
- Third , eventListener will be executed as it comes under the callback queue
- Fourth, setTimeout will be executed , since it’s the part of macrotask queue which has the least priority.
Few question on event loop and task queue
Question 1
console.log('Start'); const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms)); delay(1000).then(() => { console.log('Delayed function'); }); console.log('End');
Question 2
setTimeout(function () { console.log(1); }, 0); console.log(2); Promise. resolve().then(() => { console.log(3); }); setTimeout(function () { console.log(4); }); console.log(5);
Question 3
console.log('Start'); setTimeout(() => { console.log('Inside setTimeout 1'); }, 0); new Promise((resolve, reject) => { console.log('Inside Promise constructor'); resolve(); }) .then(() => { console.log('Inside Promise then 1'); return new Promise((resolve, reject) => { console.log('Inside nested Promise constructor'); resolve(); }); }) .then(() => { console.log('Inside Promise then 2'); }); setTimeout(() => { console.log('Inside setTimeout 2'); }, 0); console.log('End');