Node.js animated: Event Loop
Tags: javascript, node, beginners, webdev
Published: 2022-11-05 18:15:13

We have all heard about JavaScript and Node.js being single-threaded, but what does it mean in practical terms?

It means that JavaScript can do one thing at a time. For example, we cannot simultaneously multiply and sum numbers. We usually do operations in sequence. We add and then multiply or vice versa. Modern computers are fast, and the result of two or more consecutive tasks seems to be computed simultaneously, but there are exceptions.

We all have tried to scrape data from that slow website or waited more than thirty seconds before getting the result of a database query. Do we want to block our single thread from executing more tasks because of a slow database query? Luckily, Node.js doesn’t stop from running other operations because of Libuv, a C++ library responsible for the event loop and asynchronously handling tasks such as network requests, DNS resolution, file system operations, data encryption, etc.

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.

![Code sample to showcase the event loop](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j7r4s8bxdbv73bv93vit.png)


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.

![Function invocation on Node.js call stack](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m2ja8tymo646or3emo07.gif)


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.

![Libuv handles I/O ops](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l2vxqbfq6r7e55up4bnz.gif)

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

![Processing I/O while Node.js runs our code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5dnrdqoql3sp9rw0gt1x.gif)

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 latter is empty and moves the first queue item for execution.

![The event loop checks for an empty call stack](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pp9n3grfwgcaqgi30t4e.gif)

The code is available at https://github.com/fabrilallo/event-loop-1

## Pop quiz on the event loop

Try to figure out what the following code prints on the console.

![A more complicated code sample to showcase the event loop](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lu4v4a7ryrp347glwrf1.png)

![An animated guide for the event loop](https://imgur.com/1sV8nGA)

## 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](https://dev.to/nodedoctors/animated-nodejs-event-loop-phases-1mcp), we will explore in greater detail how **timers**, **I/O**, **promises**, and **ticks** are handled by the different phases of the event loop.

If you liked the article, follow us on Twitter @fabriziolallo  and @AndrewHu368