The Last Event Loop Guide you will Ever Need
Tags: node, javascript, learning, codenewbie
Published: 2024-03-17 04:45:51

Yes, I said it. This is it.

> **💡 Read this Guide end to end to understand exactly how the Dreaded Event Loop in Javascript or NodeJS works.**

## Step 1️⃣ : Synchronous and Asynchronous
As a developer, you need to understand every code you write needs to be executed either Synchronously or Asynchronously.

### Synchronous
Synchronous execution is when your program is executed line by line. 

Take this code snippet for example : 
```javascript
console.log("Entry 👇🏻");

function add(firstNumber, secondNumber){
   return firstNumber + secondNumber;
}
console.log("Function Called : ",add(2,5));
console.log("Below function 🧐");

```

The output is : 
```java
Entry 👇🏻
Function Called : 7
Below function 🧐
```

Pretty simple right? The code follows a top to bottom approach of execution, with the function returning the sum immediately.

Let's take a different scenario.

### Asynchronous
Asynchronous code is simply put to work on a separate context for execution. This doesn't mean that it is not being executed.

> 💡 Asynchrony, in computer programming, refers to the occurrence of events independent of the main program flow and ways to deal with such events.

This essentially means tasks that can be delegated away from the main thread of execution. 

Let's take an example of reading data from a file using NodeJS. 

```javascript
const fs = require("fs");
console.log("Entry 👇🏻");

fs.readFile('sample.txt', 'utf8', (err, data) => {
    if (err) {
      // Handle error if file reading fails
      console.log("Error reading file");
    } else {
      // Invoke callback with file content
      console.log("File reading done. Contents 👇🏻\n",data);
    }
 });

console.log("Below function 🧐");
```

**Can you guess the Output?**

Let me help you.

```java
Entry 👇🏻
Below function 🧐

File reading done. Contents 👇🏻
Hello, I am the content in sample.txt file!!

```

Can you spot the difference? 
This is what asynchronous programming helps us do. 

File reading is a CPU heavy process(if for small files, this takes more time than a simple program execution).

But this is not the reason that the contents are displayed after the `console.log` after the file reading method.

This happens because NodeJS defines `fs.readFile` as an asynchronous task. And NodeJS gives priority to Synchronous tasks over Asynchronous tasks. 

## Step 2️⃣ : Understanding the NodeJS environment 
NodeJS is a Library built to run Javascript outside of the browser. 

We will not get into the details of why and how this is done. 

But let's get into how NodeJS handles the execution of a program.

NodeJS internally has 3 main parts that handle the execution of a Javascript program. 

For the above 2 programs, let's see individually how NodeJS handles execution internally using the images below(for Better Understanding) : 
### First Program : 
<img src="https://github.com/thevinitgupta/100-Days-of-Learning/assets/65801700/531d40f5-12be-45c2-9a64-919debb71877" alt="nodejs internal working" />

**To understand the working of the second program, read the section below with the simulation**


## Step 3️⃣ : Understanding the Thread Pool and Callback Queue
For all the non-blocking code, it passed to the Thread Pool implemented using LibUV library. 

The threads are tasked with executing the Asynchronous tasks outside of the main thread. This helps NodeJS execute so many network calls at once, even though Javascript is a `Single-Threaded Language`.

- The **Threads process the tasks** and pass the callbacks into the callback queue.

- The Callbacks are **queued according to a certain priority**, which we will discuss in the below sections.

> ### 💡 By default there are 4 working threads in Libuv. But you can increase them upto : MAXIMUM NO. OF CPU CORE AVAILABLE which you can get using the code below : 
```js
const max = os.cpus().length;
```

- Callbacks are picked up by the Event Loop and pushed onto to the Call Stack of Javascript, **ONLY WHEN THE CALLSTACK IS EMPTY**.

<img src="https://github.com/thevinitgupta/100-Days-of-Learning/assets/65801700/da3a2235-9586-489f-8f23-f0619ac7c5a5" alt="asynchronous code execution in NodeJS" />

## Step 4️⃣ : The Event Loop
The Event Loop is nothing but a scheduling algorithm. 

Yes, it is that simple. 

A scheduling algorithm that defines which callbacks are to be prioritized over the others. 

But before understanding the order, understand that there are 6 types of callbacks, based on the calling instance. 

### 6 Types of callbacks : 
- **Timer Callbacks** : You might have used the `setTimeout` and the `setInterval` methods.

- **I/O Callbacks** : Input/Output operations are the File reading and Network based operations.

- **Check Callbacks** : There is a NodeJS specific function : `setImmediate` used to execute a Callback as soon as the current event loop finishes. 
This is basically like the Hooks in ReactJS, which helps us hook into the lifecycle of NodeJS execution.

- **Close Callbacks** : For the I/O operations, we have event listeners to listen to the `closing` event. Once the event is fired, these callbacks are defined to be executed.

- **Promise Callbacks** : When promises are invoked, we supply callbacks to be called based on the result of the promise. 

- **Next Tick Callbacks** : Next Tick is a function native to NodeJS modules (`process.nextTick()`) used by developers in real-time applications every day to **defer the execution of a function** until the next Event Loop Iteration.


The Event Loop schedules the callbacks, which is visualized in the following diagram : 


![Event Loop Visualized](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8eeq2m3wnpes8tbpwkli.png)


I know it might be overwhelming, but is simple. 

### The steps are as follows : 
1. **Check if callstack is Empty**, then Proceed as follows.

2. Callbacks in the **Microtask Queue** which is divided in 2 parts : 
   i)  Execute the `nextTick` callbacks.
   ii) Execute the `Promise` callbacks.

3. Callbacks in the **Timer Queue**, but there is a catch here. 
> 🚨 After every callback in the **Timer Queue** is executed, **REPEAT STEP 2(`Microtask Queue`)** before moving to next callback in Timer Queue.

4. Execute callbacks in the **I/O Queue**.

5. **REPEAT STEP 2 (`Microtask Queue`)**

6. Execute Callbacks in the **Check Queue** i.e. the `setImmediate` callbacks, but there is a catch again.
> 🚨 After every callback in the **Timer Queue** is executed, **REPEAT STEP 2(`Microtask Queue`)** before moving to next callback in Timer Queue.

7. Execute all the callbacks in the **Close Queue**

8. **REPEAT STEP 2 (`Microtask Queue`)**

9. Check if there process needs to repeated. If NOT 👉🏻 then EXIT.

<img src="https://media.giphy.com/media/lOVEObyuXIY3xNLDpd/giphy.gif?cid=790b76115lshhm6gwnpj2szcfaedahu679q7ukdvyzu1xqmz&ep=v1_gifs_search&rid=giphy.gif&ct=g" alt="exhausted"/>

This is the Event Loop steps simplified.
### But we are Developers. Of-course we need examples. 

So here are a few links which you can use for examples : 
- [Next Tick and Promise Queues](https://www.builder.io/blog/NodeJS-visualizing-nextTick-and-promise-queues)

- [Event Loop](https://www.javascripttutorial.net/javascript-event-loop/)

- ### The Original Video on Event Loop
 {%embed https://youtu.be/8aGhZQkoFbQ?si=Tx5EVV0fLES5M6zo %}