Skip to main content

Command Palette

Search for a command to run...

The Node.js Event Loop Explained

Published
β€’4 min readβ€’View as Markdown
The Node.js Event Loop Explained
A

I’m Arjun Saxena, a passionate software developer specializing in web engineering. I believe in writing code that creates real solutions to real problems. I love building efficient, user-friendly applications and constantly push myself to learn new technologies. Beyond coding, I enjoy sharing knowledge and growing together with others in the tech community.

β€œNode.js is single-threaded… then how does it handle so many users?”

The short answer is πŸ‘‰ The Event Loop

In this article, we’ll understand:

  • What the Node.js Event Loop is

  • Blocking vs Non-blocking code

  • How Node.js handles multiple requests with a single thread

  • Async code using callbacks and promises
    All explained in a very simple & beginner-friendly way.

A Simple Analogy: A Chef Handling Multiple Orders 🍳

Imagine a restaurant with one chef.

  • Customers place orders

  • Some food takes time to cook

  • The chef does not wait doing nothing

  • While food is cooking, the chef takes other orders

πŸ‘‰ This is exactly how Node.js works

Real LifeNode.js
ChefSingle thread
OrdersUser requests
CookingAsync tasks
Order systemEvent Loop

What Is the Node.js Event Loop?

The Event Loop is a system inside Node.js that:

  • Keeps track of tasks

  • Executes callbacks

  • Handles async operations

  • Makes Node.js non-blocking

πŸ‘‰ It decides what code should run next

Single Thread β‰  Single Task ❗

Node.js:

  • Has one main thread

  • But can handle many requests

  • Because long tasks are handled asynchronously

That’s the power of the event loop πŸ’ͺ

Blocking Code (Bad ❌)

Blocking code stops everything until it finishes.

Example (Blocking)

const fs = require("fs");

const data = fs.readFileSync("file.txt", "utf-8");
console.log(data);

console.log("This runs last");

πŸ‘‰ Node.js waits for the file
πŸ‘‰ No other request can be processed
πŸ‘‰ Bad for servers ❌

Non-Blocking Code (Good βœ…)

Example (Non-Blocking)

const fs = require("fs");

fs.readFile("file.txt", "utf-8", (err, data) => {
  console.log(data);
});

console.log("This runs first");

πŸ‘‰ File reading happens in background
πŸ‘‰ Event loop keeps running
πŸ‘‰ Server stays fast πŸš€

Blocking vs Non-Blocking (Easy Comparison)

BlockingNon-Blocking
Stops executionContinues execution
Slow serversFast servers
Simple but riskySlightly complex but scalable

How Node.js Handles Multiple Requests 🧠

Let’s say:

  • User A β†’ file request

  • User B β†’ API request

  • User C β†’ form submission

Node.js:

  1. Accepts all requests

  2. Sends slow tasks to background

  3. Event loop continues running

  4. Responds when tasks are done

πŸ‘‰ No request waits in a long line

Event Loop Phases (Simplified)

The event loop runs in cycles.

https://media.geeksforgeeks.org/wp-content/uploads/20200224050909/nodejs2.png

Main Phases (Beginner View)

  1. Timers β†’ setTimeout, setInterval

  2. I/O Callbacks β†’ file & network

  3. Poll β†’ waits for new tasks

  4. Check β†’ setImmediate

  5. Close callbacks

The loop repeats again and again πŸ”

Callbacks Explained Simply πŸ”

A callback is:

A function that runs after a task finishes

Example

setTimeout(() => {
  console.log("Task completed");
}, 2000);

console.log("Waiting...");

Output

Waiting...
Task completed

πŸ‘‰ Task goes to background
πŸ‘‰ Callback runs later

The Problem with Callbacks 😡

Too many callbacks lead to callback hell.

task1(() => {
  task2(() => {
    task3(() => {
      console.log("Done");
    });
  });
});

❌ Hard to read
❌ Hard to maintain

Promises: A Better Way 🀝

Promises make async code cleaner.

Example

fetchData()
  .then(data => processData(data))
  .then(result => console.log(result))
  .catch(error => console.log(error));

Promise States

StateMeaning
PendingStill running
FulfilledSuccess
RejectedFailed

Async / Await (Best & Cleanest ✨)

async function getUser() {
  try {
    const user = await fetchUser();
    console.log(user);
  } catch (err) {
    console.log(err);
  }
}

πŸ‘‰ Looks synchronous
πŸ‘‰ Works asynchronously
πŸ‘‰ Uses event loop internally

Blocking vs Non-Blocking Flow Diagram

https://bytearcher.com/articles/blocking-vs-non-blocking-in-node.js/process_state_diagram01.gif

Blocking Flow

Task A β†’ wait
Task B β†’ wait
Task C

https://miro.medium.com/1%2Ay8OTPaojQ9uRkxZK0Adc3Q.png

Non-Blocking Flow

Task A β†’ background
Task B β†’ run
Task C β†’ run
Callback when ready

Why the Event Loop Is So Important?

Because it makes Node.js:

  • Fast

  • Scalable

  • Memory-efficient

  • Perfect for APIs, chat apps, streaming