The Event Loop in JavaScript

The Event Loop is one of the most important topics in Javascript that we should know in detail. In this article, we are going to cover the basics of the Event Loop and how it works with single-threaded and asynchronous functions.

The first thing we should know that Javascript is a single-threaded language. That means it only executes one thing at a time. Almost all browsers have an Event Loop for every tab, which helps to run every process in isolation and avoid a web page with infinite loops or heavy processing.

Call Stack:

The call stack is a stack that holds the calls in the LIFO queue (Last In, First Out).

The Event Loop keeps checking if there’s anything in the call stack that needs to run. In this process, the Event Loop adds any function call it finds to the call stack and executes in order.

Let's see our first example:

You can see the call stack in the error section. where two() is called after one().

A Simple Example:

In this example, we have three functions called country, state, and city.

const city = () => console.log("city");const state = () => console.log("state");
const country = () => { console.log("country"); state(); city();}country();

This will have output:

countrystatecity

When this code runs, country() is called first. Inside country() we call state() and then we call city().

Here’s a visualization of our call stack:

Every block represents the Event Loop iteration, it will iterate until the call stack is empty.

The Message Queue:

Now let's see how the call stack will look if we use setTimeout:

const city = () => console.log("city");const state = () => console.log("state");
const country = () => { console.log("country"); setTimeout(state,0); city();}
country();

Our output will look like this:

countrycitystate

When this code runs, country() is called first. Inside country() we call setTimeout, passing state as an argument with a timer set to 0. Then we call city().

At this point, the call stack looks like this:

In JavaScript when setTimeout is called, the browser or Node.js starts the timer. After the timer expires it calls the callback function.

In this case, we put 0 as the timeout so the callback function is put in the Message Queue.

Click events, keyboard events, DOM events, or fetch responses are also queued in the message queue.

The Event Loop gives priority to the call stack and first processes everything it finds. After the call stack is empty it goes to execute things in the message queue.

The Job Queue (ES6):

Apart from Message Queue, there is another concept in ES6 called Job Queue which is used by Promises. It executes the result of an asynchronous function as soon as possible instead of putting them at the end of the call stack.

Promises that resolve before the current function ends will be executed right after the current function.

Let’s see another example:

const city = () => console.log("city");const state = () => console.log("state");
const country = () => { console.log("country"); setTimeout(state,0); new Promise((resolve, reject) => resolve("After city and before state") ).then(resolve => console.log(resolve)); city();}country();

The output should look like this:

countrycityAfter city and before statestate

Now you have a better idea about the difference between Promises and old asynchronous functions or other platform APIs. I hope y’all found this informative! I’ve been diving more into the under-the-hood side of JavaScript, so expect more blog posts! As always, feel free to reach out to me on my LinkedIn. Happy coding!

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store