Behind Node.js - The Event Loop

Wojciech Parys
October 15, 2019

Node.js is a JavaScript runtime built on Chrome’s V8 JavaScript Engine. That you can read at the home page of nodejs.org. But what Node.js exactly is? How does it work? In this article we will dive into core features of this runtime environment. So let’s move on.

What does mean Javascript Runtime

You probably know what JavaScript is. It’s a programming language, typically used in a browser to manipulate DOM, or to implement some behaviour, like for example opening popups and modals, or interaction with user after the page was loaded.

However, JavaScript is not limited to that. Node.js, which is said to be a “different version of JavaScript”, is basically build on JavaScript, with some features added, and with some features removed, compared to JS running in a browser. It was modified to allow you to use JavaScript on the server side, like any normal programming language used in your computer programs.

NodeJS Architecture A

Node.js uses V8 engine - a JavaScript engine written in C++, that was built by Google and runs JS in the browser. That means that engine takes JavaScript code - the code running in your browser or the Node.js code - and compiles it to the machine code. Node.js takes codebase and adds some features, like working with your local file system, that browser can’t do for security reasons. Of course, some features are missing, like DOM manipulations, cause you don’t have any DOM at the server side ;-)

NodeJS Architecture B

Single- or Multi-Threaded

One important thing is that Node.js uses only one single JavaScript thread (process). So how is it able to handle multiple requests or operations? Let’s say your program accesses the file system. Operations on file system are really fast, but when you have very big files this can be time consuming. So if you’re doing this for an incoming request, a second request might be blocked because you’re not able to handle it yet, or it might even get declined, so your page is basically down for this request. Here the event loop comes in handy.

The event loop is automatically started by Node.js when the program starts. This loop is responsible for handling event callbacks, so it runs some code when a certain event occurs. It doesn’t handle your file operations, it only fires callbacks that you defined when for example the file write is done. That code will be handled in the event loop but it will finish very fast. What about file system operations? They are send to Worker Pool which is also managed by Node.js automatically. This worker pool is responsible for all the heavy lifting and it runs on multiple threads. It’s closely integrated with the operating system you’re running the app on, so it is really detached from your code. So this is where the magic happens. Once the worker is done, it will trigger the callback, and since the event loop is responsible for all events and callbacks, it will end up in the event loop.

Event Loop Multithreading

So let’s take a closer look at the event loop…

Event Loop explained

Event loop is just an infinite loop which is started by Node.js that keeps the Node.js process running. As I mentioned, it handles all the callbacks and it has a certain order in which it goes though the callbacks. The following diagram shows an overview of the event loop’s order of operations:

Event Loop Explained

Timers

This phase executes callbacks scheduled by setTimeout() and setInterval(). A timer specifies the threshold after which a provided callback may be executed rather than the exact time a user wants it to be executed. Timers’ callbacks will run as early as they can be scheduled after a specified amount of time has passed. However, Operating System schedulers or the running of other callbacks may delay them.

Pending callbacks

In this phase I/O-related callbacks will be executed, deferred to the next loop iteration. For example, if you registered a callback fired after write or read to file has finished, or some network operation is completed, this callback will run in this phase.

Idle, prepare

They’re only used internally.

Poll

It’s basically a phase where nodejs looks for a new IO events and do it’s best to execute their callbacks immediately if possible. If not, it will defer a callback execution and register this as a pending callback. So it has two main responsibilities:

  1. Calculate how long it should block until next I/O polling
  2. Process events in the polling queue.

It also checks if there are any timer callbacks and if so, it jumps to that timer phase and execute them right away. This means that it can jump back not completing the iteration. If there are no timers awaiting it will continue.

Check

setImmediate() callbacks are invoked here. This is something like setTimeout or setInterval, but it will execute immediately, after any open callbacks have been executed.

Close callbacks

Here node execute all “close” event callbacks. So if you registered any close event in your code, eg: socket.destroy() this is, where it will be executed.

Conclusion

So this is basically how Node.js event loop works. If you would like to delve even deeper into the topic, there is a lot of interesting stuff in the Node.js documentation, where you can read more and for example find differences between setImmediate and setTimeout functions, and understand the process.nextTrick() method.

Now, let's talk about your project!

We don't have one standard offer.
Each project is unique, rest assured that we will approach the next one full of energy and engagement.

LET'S CONNECT