A re-introduction to Node JS event loop

Neelesh Dwivedi
The Startup
Published in
5 min readJun 27, 2020

Whenever we startup a node program on our computer node automatically creates one thread and then executes all of our code inside that one single thread. Inside that one thread node sets up what we call an event loop. You can think of event loop as a control structure which decides what our node program must be doing at any point of time in that one single thread. Event loop is the absolute core of every node program and understanding event loop is very important as most of the performance issues boils down to eventually how the event loop behaves. So if we understand event loop we will be very well equipped to understand performance issues in node as well.

Whenever we start an application by writing node app.js to the terminal to the point that we are able to see some output on the console, a lot of things happens in between. Creation of event loop is one of those things.

We launch our node application by writing node app.js. The event loop is not created write away, first node just scans through all the contents of our files and allocates some memory in the heap to all the variables declared. Event loop is created after this process is done.

We are simulating the working of event loop with a while loop. The execution of the body of the event loop is called a ‘tick’. So in our case the body of the while loop executes in a tick.

Just like any other while loop our while loop will also require some condition which decides when to stop and similarly likely event loop also requires some condition which tells it when to stop. For this we are going to write some helper function called shouldContinue which will serve as the condition for our fake event loop. Now as long as shouldContinue returns something truthy our event loop will continue running and when it returns something falsy our program will exit back to the terminal.

Inside of this shouldContinue function node js makes three checks to decide if our event loop will continue running.

Check #1: Are there any functions that have been registered with setTimeout, setIneterval or setImmediate and still needs to be executed.

Check #2: The second check node makes is to look for any pending operating system tasks. An example of an operating system task would be a HTTP request listening on some port.

Check #3: The third check node makes is to look for any long running operations that are still being executed in our program. An example of a long running operation would be a function call inside of the fs module.

But what does it really mean to say to check for any operating system task or any long running operation. Well I think that in all the three cases node might be creating an array of some sort that keep tracks of all the pending tasks that might be created. We will also be keeping three arrays inside of our application that will mimic node’s way of keeping track of all the tasks and in the shouldContinue function we will return the length of all the three arrays. So as long as there is some pending task in any of the array the event loop will continue to run for another tick.

We’re now going to move to the body of our event loop.We’re going to write out a series of comments that explain what occurs during every single tick. So these steps are occurring very very quickly again and again and again.

So the very first thing occurs is node looks at that array of pending timers and it looks at all the different functions that have been passed to set time out and set interval. If any of those timers have expired the node calls the relevant callbacks associated with each one.

The next step which happens is node looks for any pending OS task or any pending long running operation. If any one of these have been completed or any new event have been triggered the node executes the relevant callbacks. For example, if some response comes into same port that we are listening to or we have successfully retrieved some data from a file using the fs module.

Now moving on to the third step is where the things start to become really interesting. During the third step node just pauses all the execution temporarily and decides to wait for any of the following things to occur.

  1. a new pending OS task is done
  2. a new pending operation is done
  3. a timer is about to complete

Once that pause is complete we then move on to last 2 steps. In the next step node once again looks for pending timers but this time it has nothing to do with setInterval and setTimeouts. It only looks for functions that has been registered with setImmediate.

In the final steps node handles all the close operations. Like closing the file connection with fs.close() or someother function which deals with closing.

So this would be my attempt to explain event loop in node as simple I could. Hope you guys like it.

--

--

Neelesh Dwivedi
The Startup

A burning sense of passion is the most potent fuel for your dreams.