NodeJS Event Loop (original) (raw)

Last Updated : 12 Feb, 2025

The event loop in Node.js is a mechanism that allows asynchronous tasks to be handled efficiently without blocking the execution of other operations. It:

Why Event Loop is important?

The Event Loop is essential in Node.js because it allows non-blocking, asynchronous operations to be handled efficiently, even though Node.js operates on a single thread.

**Let’s see a simple Asynchronous example

JavaScript `

console.log("This is the first statement");

setTimeout(function() { console.log("This is the second statement"); }, 1000);

console.log("This is the third statement");

`

**Output

This is the first statement This is the third statement This is the second statement

**How the Event Loop Works?

When a Node.js application runs, the event loop starts, processes the synchronous code first, and then moves to handle asynchronous tasks. The execution follows these steps:

1. Initialization

When Node.js starts, it loads the script, executes synchronous code, and registers any asynchronous tasks (e.g., timers, I/O requests, network operations).

2. Execution of Input Script

3. Handling Asynchronous Operations with libuv

Node.js uses a special C library called libuv to handle asynchronous operations. This library manages a thread pool that offloads heavy tasks (like file I/O, database operations, or network requests) that would otherwise block the event loop. The thread pool contains several threads that perform tasks like:

4. Callback Execution

Once the thread pool completes its tasks, it sends callbacks to the event queue. The event loop processes these callbacks, but only when the call stack is empty (i.e., when no synchronous code is currently executing).

5. Event Loop Phases

The event loop goes through multiple phases, each designed to handle a different set of operations. It checks for events, handles asynchronous callbacks, and executes tasks in the correct order.

6. Callback Execution from Event Queue

After the call stack is empty, the event loop picks tasks from the event queue and sends them to the call stack for execution. These tasks could include:

The following diagram is a proper representation of the event loop in a Node.js server:

Event Loop Working

**Phases of the Event loop

The event loop in Node.js consists of several phases, each of which performs a specific task. These phases include:

Phases of the Event loop

**1. Timers Phase

This phase processes timers that have been set using setTimeout() and setInterval().

JavaScript `

console.log('Start');

setTimeout(() => { console.log('Timeout callback'); }, 2000);

console.log('End');

`

**Output:

Start End Timeout callback

**2. Pending Callbacks

This phase executes I/O-related callbacks that were deferred from the previous loop cycle.

JavaScript `

console.log('Start');

setImmediate(() => { console.log('Immediate callback'); });

console.log('End');

`

**Output:

Start End Immediate callback

**3. Idle, Prepare _(Internal use only)

This phase is used internally by Node.js for background tasks.

**4. Poll Phase _(Main Phase)

The Poll phase executes most of the tasks like- I/O, file reading, HTTP requests and much more.

JavaScript `

const fs = require('fs'); const readStream = fs.createReadStream('./file.txt');

console.log('Start');

readStream.on('data', (chunk) => { console.log(chunk.toString()); });

console.log('End');

`

**Output:

Start End File read complete

**5. Check Phase

This phase processes any setImmediate() callbacks that have been added to the message queue.

JavaScript `

console.log('Start');

setImmediate(() => { console.log('Immediate callback'); });

console.log('End');

`

**Output

Start End Immediate callback

**6. Close Callbacks Phase

This phase executes callbacks for closed connections like sockets, streams, and event emitters.

JavaScript `

const net = require('net'); const server = net.createServer((socket) => { socket.on('close', () => { console.log('Socket closed'); }); });

server.listen(8000);

`

**Output

Server listening on port 8000

process.nextTick() and Promises in the Event Loop

Apart from these phases there is also process.nextTick() and promise callback which has the highest priority in the event loop. It executes after every phase before moving to the next phase.

Now you have seen all the phases so let’s understand the order by using this code example

JavaScript `

setImmediate(() => { console.log("setImmediate is called"); });

Promise.resolve("Promise is resolved").then(console.log);

setTimeout(() => { console.log("Time function is called"); }, 0);

process.nextTick(() => { console.log("Process.nextTick"); });

`

Output

Process.nextTick Promise is resolved Time function is called setImmediate is called

**In this example