Subtle differences between the Javascript and Node JS event loops (Part 1)

If you can understand the joke in the above image, you might have an intuitive understanding of the asynchronous processes in Javascript. At the end of this post, I’ll write a simple snippet that would generate the above poem.

I’m a self taught programmer who has an interest in full stack Web development. Therefore, naturally I had to learn Javascript first and then I focused on Node, since I didn’t want to learn another new language like Php to set up my backends.

When learning Node, an immediate question popped into my head, whether there’s difference between the implementation of the event loop by Node and Javascript (browser based event loop). This required studying both in some depth and I wanted to highlight some key differences that I’ve found. I’ve decided to introduce javascript event loop and how asynchronous javascript works under the hood in this post and there will be another post about node js’s event loop implementation and few contrasting differences between the two.

Javascript event loop

The most important concept to keep in the back of your head is that, contrary to the popular belief, javascript is actually single threaded. Which means that it has only one call stack and one memory heap, both of which are provided by a browser at run time.

Asynchronous operations such as doing AJAX calls, DOM manipulation and setting timeouts are all provided by something called Web APIs. Let’s look at the internal structure of Javascript run time environment by running a simple script.

The gifs were generated using a video from the brilliant udemy javascript course The Complete JavaScript Course 2020: Build Real Projects! which I’d highly recommend.

Compare code with the stack

If the code is not clear I have provided it below,

It’s a pretty simple program which consists of two functions and where the second function is called from the first function. The first function is called initially and then it will pop in to the stack, from there, it will log “Hey, there!” to the console. After that It will pop the second function into the stack. Which in turn would call the setTimeout function.

Now, this setTimeout function is not part of the core Javascript language and it is only provided by the browser at run time using Web APIs. Let’s see what happens after this.

Timeout function is returned to the WEB APIs

The setTimout() function is returned to the WEB APIs and it will remain there until it has finished the task that it has been assigned to. In this case, it is to remain 2 seconds before running the callback function inside. After this, the second function will be popped off the stack and the javascript engine will keep executing the program sequentially until the main thread returns to the global execution context.

Compare code with the stack and console

This time it has ran the final console log and the stack is now empty except for the global execution context as usual. Now, the question is that, what has happened to the callback function inside our setTimeout.

Call back function is returned to the message queue

After the timeout interval is over, the callback function will be sent to something called the message queue. In here, this will wait until it gets called. So, the function of event loop is to monitor both the stack and message queue constantly and if the stack is empty it will pick up the first callback function in the message queue and it will put it inside the stack. It will do this process until the message queue becomes empty.

The callback is provided to the stack by the event loop

So, this is what the Javascript event loop does in a nut shell. Now going back to our initial poem, I can write a simple script like this.

Notice that, for the setTimout I have put 0ms. However, the line, console.log(“And so are you”) will be executed before that since, Javascript always run the main thread first before running the asynchronous callbacks.

In the next part, we will look at how Node JS implements this event loop.

A fullstack engineer who's passionate about building data intensive products and distributed systems. My stack includes Golang, Rust, React, NodeJS and Python.