DEV Community

Cover image for Ultimate guide on the JavaScript Event loop
Srishti Prasad
Srishti Prasad

Posted on • Edited on

Ultimate guide on the JavaScript Event loop

In this blog I've provided a thorough explanation with images and a clearly described examples.

JavaScript is a single threaded language with one call stack and it can do only one thing at a time, & this Call stack is present in JavaScript engine & all the code of JavaScript is executed inside the call stack.
The call stack is used by JavaScript to keep track of multiple function calls. It is like a real stack in data structures where data can be pushed and popped and follows the Last In First Out (LIFO) principle
The main job of the call stack is to execute all the code that comes inside it & it doesn't wait for anything.

paint2-copy

So, as stated above JavaScript call stack executes code without waiting for anything , so what if we need to wait for some function ? How will things execute in that case?
How JavaScript perform async task?

Now, let’s understand what is the scene behind browser.

Inside browser we have JavaScript engine inside which we have our call stack.
Browser or Web APIs are built into your web browser, and are able to expose data from the browser and surrounding computer environment and do useful complex things with it. They are not part of the JavaScript language itself, rather they are built on top of the core JavaScript language, providing you with extra superpowers to use in your JavaScript code.
Some of Web APIs are - setTimeout(),DOM APIs, fetch(),localStorage,console.log(),location
All these are not JavaScript instead they are part of browser which it give access so as to use it inside our call stack because of global object called window .So browser give JavaScript to use these Web APIs inside JavaScript engine with the help of global object window.

NOTE-Although we don’t write window.console.log() always because its a global object and can be accessed directly.

Now lets understand how setTimeout() works behind the scene in browser.

console.log("hello");
setTimeout(function callbck(){
   console.log("your 5 second is over");
},5000);
console.log("Bye");

Enter fullscreen mode Exit fullscreen mode

Img1
Output in console will be:-

Hello
Bye
your 5 second is over

Enter fullscreen mode Exit fullscreen mode

ss168
Here, we can see setTimeout() function in call Stack

Let's see how this code is executed line by line.

  • JavaScript code executes line by line so “console.log("hello")” will call consol.log web API and print “Hello” in console then,

  • as soon as it encounter setTimeout() it will execute after the specified time and till then further code line will execute that is it will print “Bye” in console

  • when the time is over of setTimeout() it will go to callback queue and as soon as event loop detect something is waiting in callback queue, it will send it to call stack to execute the code & prints “your 5 second is over” in console.

  • Console.log is web API which is called every time whenever required.

Before moving forward let's understand what is Callback Queue, Event Loop, Microtask Queue

Callback Queue: After the timer gets expired, the callback function is put inside the Callback Queue, and the Event Loop checks if the Call Stack is empty and if empty, pushes the callback function from Callback Queue to Call Stack and the callback function gets removed from the Callback Queue. Then the Call Stack creates an Execution Context and executes it.

Event Loop :Event loop is an endless loop, which waits for tasks, executes them and then sleeps until it receives more tasks.
The event loop executes tasks from the event queue only when the call stack is empty i.e. there is no ongoing task. The event loop allows us to use callbacks and promises.

Microtask Queue: Microtask Queue is like the Callback Queue, but Microtask Queue has higher priority. All the callback functions coming through Promises and Mutation Observer will go inside the Microtask Queue. For example, in the case of .fetch(), the callback function gets to the Microtask Queue. Promise handling always has higher priority so the JavaScript engine executes all the tasks from Microtask Queue and then moves to the Callback Queue.

Similar to setTimeout() event listeners also which takes callback function when it encounters click/keypress(etc) then it is pushed to call stack from callback queue to execute the code.

console.log("hello");
document.getElementById("btn").addEventListener("click",function cb(){
    console.log("callback");
})
console.log("Bye");

Enter fullscreen mode Exit fullscreen mode

Output in console will be :

Hello
Bye
Callback (if button encounters click/keypress..)

Enter fullscreen mode Exit fullscreen mode

But, if we consider fetch, things work bit differently

Fetch function returns a promise and we have to pass a callback function which will be executed once the promise is resolved.
Let's understand how this code will be executed.

console.log("start");
setTimeout(function callback1(){
    console.log("will execute after 5 second");
},5000);
fetch(https://api.netflix.com).then(function callback2(){
    console.log("fetching data from api");
})
console.log("end");

Enter fullscreen mode Exit fullscreen mode

paint2

  • For the 1st line of code ,it will call console.log from web API and print “start” in the console.

  • Since setTimeout is to be executed after 5 seconds so it will register this call in the web API,after 5sec ,this call back will go to callback queue waiting for event loop to call this to call stack for it to be executed .

  • Meanwhile, fetch() will also register call in webApi and as soon as it gets data from API it will go to micro task queue waiting for event loop to call this to call stack for execution.

Here, fetch will execute faster than setTimeout.

Now the question comes what will happen if we have task in both micro task queue and call back queue(Task queue)
Since microtask queue has higher priority so first all the task of micro task queue will be completed then callback queue.

paint3

Conclusion:
JavaScript language is single-threaded and the asynchronous behaviour is not part of the JavaScript language itself, rather they are built on top of the core JavaScript language in the browser (or the programming environment) and accessed through the browser APIs(Web APIs).

If you have any questions, leave a comment and I'll do my best to respond.
Give this article a like if you found it helpful and follow me for more articles like this.

Top comments (2)

Collapse
 
neohed profile image
Dave

Very good explanation of a really important subject - great job. This knowledge is absolutely essential to mastering JavaScript. I have been asked questions related to this subject in several job interviews.

Collapse
 
srishtikprasad profile image
Srishti Prasad

“Thank you Dave! I really appreciate you taking the time to express that.”