Node.js Event Loop Introduction

Emad Elmogy
3 min readFeb 14, 2023

--

The event loop is a core Node.js concept. It allows you to learn about Node’s asynchronous processes and non-blocking I/O. It describes the mechanisms that contribute to Node’s success, power, and popularity as a modern framework.

Despite the fact that Node.js is single-threaded, Node.js uses an event loop to perform non-blocking I/O operations.

What happens under the hood when Node.js works on tasks such as database queries? We will explore it by following this piece of code step by step.

The V8 JavaScript engine manages a call stack, an essential piece that tracks which part of our program is running. Whenever we invoke a Javascript function, it gets pushed to the call stack. Once the function reaches its end or a return statement, it is popped off the stack.

In our example, the line of code console.log('Starting Node.js') is added to the call stack and prints Starting Node.js to the console. By doing so, it reaches the end of the log function and is removed from the call stack.

The following line of code is a database query. These tasks are immediately popped off because they may take a long time. They are passed to Libuv, which asynchronously handles them in the background. At the same time, Node.js can keep running other code without blocking its single thread.

In the future, Node.js will know what to do with the query because we have associated a callback function with instructions to handle the task result or error. In our case, it is a simple console.log, but it could be complex business logic or data processing in production applications.

While Libuv handles the query in the background, our JavaScript is not blocked and can continue with console.log(”Before query result”).

When the query is done, its callback is pushed to the I/O Event Queue to be run shortly*.* The event loop connects the queue with the call stack. It checks if the call stack is empty and moves the first queue item for execution.

Conclusion

The event loop, the delegation, and the asynchronous processing mechanism are Node.js’s secret ingredients to process thousands of connections, read/write gigantic files, handling timers while working on other parts of our code.

In the article, we saw the vital role of Libuv and its ability to handle numerous potentially long-running tasks. At the same time, we went through the event loop and its role as a bridge/connector between callbacks of asynchronous operations in the I/O event queue and the call stack. In the following articles, we will explore in greater detail how timers, I/O, promises, and ticks are handled by the different phases of the event loop.

--

--