In the last article, we learned 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.
The way these two codes execute in JavaScript is completely different.
Since JavaScript is a single-threaded language, execution starts from top to bottom.
In Code 1, execution moves line by line sequentially.
In Code 2, because setTimeout is part of the Web APIs, the execution flow changes.
Output Comparison
Code 1 Output:
Plaintext
start
inside function
end
Code 2 Output:
Plaintext
start
end
inside function
Adding event loop to the execution flow
Step 1: As soon as the JS engine encounters the <script> tag, it creates a Global Execution Context inside the Call Stack.
Step 2: It encounters the first log statement and prints "start".
Step 3: It finds setTimeout. The callback of setTimeout is offloaded to the browser's Web APIs memory, and a timer of 2 seconds is attached to it.
Step 4: Since JS engine is single-threaded, execution moves forward immediately, printing "end".
Step 5: Once the 2-second timer finishes, the callback function is pushed to the Task Queue (specifically the Macrotask Queue), waiting for the Call Stack to empty.
Step 6: Now comes the job of the Event Loop. Its main responsibility is to check if the Call Stack is empty. Once empty, it moves tasks from the Task Queue to the Call Stack.
Step 7: The setTimeout callback function is pushed to the Call Stack and executed.
Step 8: The Call Stack becomes empty, and execution ends.
Now go ahead and drink some water 🥛
Definition of all the jargons
Call Stack
Keeps track of function calls, managing their execution order and maintaining the program state.
Web APIs
APIs provided by the browser to extend functionality. Examples: HTTP/HTTPS requests, DOM API, fetch, Event Listeners, setTimeout, etc.
Task Queue / Callback Queue
Holds tasks resulting from input events, timer events, and other Web API callbacks.
Microtask Queue
Holds tasks associated with Promises. It has higher priority than the Macrotask Queue.
Start
Inside Promise constructor
End
Inside Promise then 1
Inside nested Promise constructor
Inside Promise then 2
Inside setTimeout 1
Inside setTimeout 2
Explanation:Synchronous execution: "Start", then the Promise constructor body executes synchronously logging "Inside Promise constructor", then "End".Microtasks: The first .then() runs logging "Inside Promise then 1", executing its nested constructor synchronously to log "Inside nested Promise constructor". The chained .then() runs immediately after as a microtask, logging "Inside Promise then 2".Macrotasks: The two setTimeout callbacks run sequentially: "Inside setTimeout 1", then "Inside setTimeout 2".