What exactly is Event Loop!

What exactly is Event Loop!

ยท

5 min read

You might have heard that Javascript is a synchronous single-threaded language, but it is also a combination of Synchronous and Asynchronous events. What does this mean exactly?

Let's start with the basics of how code gets executed synchronously inside a browser.

Global Execution Context

This is the default execution context in which JS code starts its execution when the file first loads in the browser. All of the global code i.e. code that is not inside any function or object is executed inside the global execution context.

When a piece of code is run in the Javascript Engine a Global Execution Context is made and pushed inside this Call Stack. Every line of the code is executed inside this.

Now take this piece of code.

function serveCoffee() {
console.log("Cappuchino Served");
}
serveCoffee();

A GEC is made and inside it, this code is run. When serveCoffee() is called a new execution context for it is made and pushed into the call stack. "Cappuchino Served" is logged on the console.

image.png

After this the execution context for serveCoffee() is popped off from the stack and then the GEC is popped off too.

image.png

Web API

Whatever is thrown inside the call stack is executed instantaneously. If we want a task to wait for a few seconds and then run we can't do it. Well, we can but JS doesn't have the ability to do so. There's no timer available to it. These powers are given to the JS engine through the browser using something known as Web APIs.

These superb APIs are provided by the browsers to facilitate the JS Engine in execution and provide various use cases.

You must have worked with these APIs before.

  • setTimeout()
  • fetch()
  • console (Yes! even console isn't a part of JS. It's a Web API :) and a part of the browser)

and many more. You can check out various Web API's on MDN here -> https://developer.mozilla.org/en-US/docs/Web/API

These APIs can be accessed inside the call stack using the global object "window". This global object is available inside the call stack with the help of the browser. We don't have to address the window object to call them though as it is implied already.

Event Queue

Imagine there is this cafe where 2 customers are waiting to give their orders. Now today there's only one waiter at work to serve them. This waiter is our single thread of execution. Let's call him X.

The customer-1 calls X to give the order and while he is taking the order customer-2 calls him too. Now X won't stop and leave for customer-2 immediately.

X will finish taking the order from customer-1 and then only go to other customer-2. JS Engine has only one call stack where It can only execute one task at a time.

Have you ever wondered why your setTimeout() isn't working the way it should? Is it executing its callback function a little later than it is supposed to do? Well, your answer is in the next paragraph.

Let's see this piece of code->

console.log("First");
setTimeout(function callback(){console.log("Second");},2000);
console.log("Third");

What do you think the answer should be?

First
Second
Third

Wrong!

The answer will be->

First 
Third
Second

Why does this happen?

Remember our waiter X? X will note down on a notepad parallelly to go to customer-2 next while taking the order.

This notepad is what our single thread uses to queue the pending tasks that have to be done next.

In JS terms we call this notepad Event Queue.

Going to Customer-2 is the next task, and once the customer-1's order has been taken he is free now. X will push the next task on the notepad to his brain and execute it immediately.

  • Event Queue is also called the Callback Queue and Task Queue so don't get confused.

Coming to your question of why the setTimeout() isn't working the way it should. After "First" is printed the setTimeout API is called. A callback function is registered along with a timer of 2 seconds. While the timer is running the execution in the call stack continues and prints "Third". Then the execution context is popped off and then the GEC is popped off. After 2 seconds the timer returns the callback to our event queue.

Finally "Event Loop" comes into the picture now๐ŸŽ‰. Event loop is a continuously running loop whose main functionality is to->

  • Check if the call stack is empty

  • Check if there is a task inside the event queue

  • If both conditions satisfy, push the task in the event queue to call stack.

If there is something inside the queue it transfers it into the call stack by creating an execution context for the callback function.

This is when it prints "Second".

image.png

Why is the Event Queue needed?

There are so many event listeners and callbacks used in a website and they all need to be catered to one by one. Suppose there is a click event listener and a user clicks on it many times, there will be many callback functions that have to be executed one by one. To ensure this, all these callback functions are piled up inside the queue. They wait for the event loop to check if the stack is empty and then push them into the stack one by one for execution. This ensures that all of them get executed.

What is the Microtask Queue?

This queue is similar to the event queue, but it enjoys a higher priority from the event loop. When a task is present in the microtask queue and the event queue, first priority to be pushed into the call stack will be given to tasks in the microtask queue. Microtask queue handles the promises and the mutation observer. If there are many tasks inside the microtask queue they all will complete their execution and only then will the chance be given to the tasks inside the event queue.

This concludes today's article on the Event Loop. There are many more things to be explored here and I'll be writing about them shortly.

If you liked the article or have any suggestions for me please reach out on @aniketxparihar at Twitter! :)

Thank You!