Understanding the Event Loop, Callback Queue, and Call Stack in JavaScript

RMAG news

Call Stack:

Simple Data structure provided by the V8 Engine.
Tracks execution of our program, by tracking currently running functions.
Our complete Js file gets wrapped in main() function and is added in Call Stack for execution.
Whenever we call a function, it’s gets added to Call Stack. Once it gets executed and finishes it gets popped out from stack.

//Basic Example

const x = 1;
const y = x + 2;
console.log(‘Sum is’, y);

/*

– This code gets wrapped in main() and main is added to Call Stack.
– log(‘Sum is 3’) added to call stack.
– On console we would get ‘Sum is 3’. Now log function is finished and gets removed from Call Stack.
– Now end of script, main function gets popped out of Call Stack.
*/

const listLocations = (locations) => {
locations.forEach((location) => {
console.log(location);
});
}

const myLocation = [‘Delhi’, ‘Punjab’];
listLocations(myLocation)

Main function gets pushed onto the call stack.
Line 1 we are declaring the function but not calling it, hence it will not get added to call stack.
Line 7 we are defining our location array.
Line 8 Function call, So it is going to be pushed to call stack and is the top item there.
listLocations will start running. pushed to call stack.
forEach is a function call so gets added to call stack. forEach calls anonymus function one time for each location.
anonymous(‘Delhi) function gets added to call stack with argument Delhi.
Now console.log function gets added to call stack. It prints Delhi, and finishes. and pops out.
anonymous(‘Delhi) finishes and pops out.
forEach is not done yet hence does not pops out. anonymous(‘Punjab) gets added to call stack.
Now console.log function gets added to call stack. It prints Punjab, and finishes. and pops out.
forEach is completed and hence poped out of call stack.
listLocations is done, hence pops out.
Script is completed. main() pops out.

Callback Queue

It’s job is to maintain a list of all of the callback functions that needs to be executed.

console.log(‘Starting Up!’);

setTimeout(() => {
console.log(‘Two Seconds!’);
}, 2000);

setTimeout(() => {
console.log(‘Zero Seconds!’);
}, 0);

console.log(‘Finishing Up!’);

main() pushed to call stack.
Line 3: setTimeout pushed to call stack.
< setTimeout is not part of JS V8 but is part of NodeJS. It’s implementation is in C++ provided by NodeJs.
setTimeout when called registers an event which is an event-callback pair. Event here is wait 2 seconds and callback is the function to run.
Another example of event-callback pair is wait for database request to complete and then run the callback that does something with the data.

This new event i.e. setTimeout function is popped and is registered in Node APIs. 2 Seconds clock starts ticking down.
While waiting for those 2 seconds we can do other stuff < Non Blocking nature of node >

Line 7: setTimeout registers another event in Node API.

Now timeout 0 seconds are up, now the callback needs to be executed.

Callback Queue comes in picture: It’s job is to maintain a list of all of the callback functions that needs to be executed. Front item gets executed first.

callback of setTimeout with 0 seconds timeout gets added to queue so that it can be executed.
But to get executed it needs to be added on Call Stack, that’s where function go to run.

Now, here Event Loops comes in picture, it looks at the call stack and callback queue, If call stack is empty then it will run items from callback queue. < This is the reason ‘Finishing Up!’ logged before ‘Zero Seconds!’ as main was in call stack, event loop is waiting for main to get popped out>

log(‘Zero Seconds!’) gets added to call stack. and message is printed on console.
main is completed and pops out.
Event loop takes item from call back queue and push to call stack. ‘Zero Seconds!’ prints.
Once 2 seconds achieved, callback(‘Two Seconds!’) added to callback queue, moves to call stack, gets executed.
‘Two Seconds!’ prints.

Non-Blocking Nature of Node.js

JavaScript is single-threaded, meaning only one function can be executed at a time.
However, Node.js and the browser environment manage asynchronous tasks using other threads.
While the call stack is executing synchronous code, the environment handles asynchronous events in the background.

Summary

Call Stack: The structure that keeps track of function calls. Only one function can run at a time.

Callback Queue: A queue that holds callbacks that are ready to be executed.

Event Loop: A mechanism that checks if the call stack is empty and if so, pushes the next callback from the callback queue to the call stack.