Showing posts with label Node. Show all posts
Showing posts with label Node. Show all posts

Sunday, April 26, 2026

Node | process.nextclick

process.nextTick() schedules a callback to run immediately after the current operation, before the event loop continues.

It runs:

  • Before Promises
  • Before timers (setTimeout)
  • Before moving to next event loop phase


Execution order

1. Current code
2. process.nextTick() ← runs here
3. Promise microtasks
4. Event loop phases (timers, poll, check...)


Example

console.log("start");
process.nextTick(() => console.log("nextTick"));
Promise.resolve().then(() => console.log("promise"));
setTimeout(() => console.log("timeout"), 0);
console.log("end");

Output

start
end
nextclick              (next click queue)
promise               (microtask queue)
timeout                (macro task queue)


When it executes 

  • After current process /code
  • Before event loop

Current execution

process.nextTick queue runs

Promise microtask queue runs

Event loop phases start

process.nextTick() schedules a callback to run immediately after the current operation, before the event loop continues and even before Promise microtasks. It uses a separate queue and has higher priority, which is why overusing it can block the event loop.

Use cases 

1. Consistenent behaviour of async

Sometimes callback runs immediately, sometimes later → inconsistent

function
getData(callback) {
callback("data"); // sync execution
}

With nextclick, always async, predictable behavior (consistent behavior)
Callback will run before next event loop

function
getData(callback) {
process.nextTick(() => {
callback("data");
});
}

2. Error Handling

Ensures:

  • Errors are always handled asynchronously
  • Matches Node.js API design

function readFile(file, callback) {

    if (!file) {
    return process.nextTick(() => {
    callback(new Error("File required"));
    });
}

// async logic...
}


Saturday, April 25, 2026

Node | get/post request cycle

In an HTTPS POST request, Node.js initiates the request via libuv, which delegates the actual network I/O to the OS. The OS performs the real work like sending and receiving data. When data is ready, it notifies libuv, which queues the callback. The event loop then executes these callbacks in the poll phase, including response handling and streaming data events.

NoteAsync/await does not make Node.js asynchronous. Node.js is already asynchronous and non-blocking by design.

What async/await does:

  • Makes async code easier to read
  • Makes error handling cleaner
  • Improves maintainability

[Node.js] → Initiates request

     ↓

[libuv] → Registers & delegates

     ↓

[OS] → Performs actual network I/O  (real worker)

     ↓

[OS signals readiness]

     ↓

[libuv] → Queues callback

     ↓

[Event Loop - Poll phase] → Executes callback


ComponentRole
Node.js    Initiates request
libuv        Registers + listens (Thread pool not used)
OS    Performs actual network work
Poll phase    Executes callbacks
Thread pool    Not used here


Example1

const https = require("https");

const data = JSON.stringify({ name: "Ghanshyam" });

const options = {
hostname: "api.example.com",
path: "/users",
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": data.length
}
};

const req = https.request(options, (res) => {
console.log("STATUS:", res.statusCode);

res.on("data", (chunk) => {
console.log("BODY:", chunk.toString());
});

res.on("end", () => {
console.log("Response ended");
});
});

req.on("error", (err) => {
console.error("Error:", err);
});

req.write(data);
req.end();


Example2 (with Promise)

function fetchData(url) {
return new Promise((resolve, reject) => {
https.get(url, (res) => {
if (res.statusCode !== 200) {
reject(new Error(`Status Code: ${res.statusCode}`));
res.resume(); // consume response to free memory
return;
}

let data = "";

res.on("data", chunk => data += chunk);
res.on("end", () => resolve(data));
}).on("error", reject);
});
}


Example4 (without async await)

fetchUser()
.then(user => fetchOrders(user.id))
.then(orders => fetchPayment(orders))
.then(payment => console.log(payment))
.catch(err => console.error(err));

Example4 (with async await)

async function process() {

  try {

    const user = await fetchUser();
    const orders = await fetchOrders(user.id);
    const payment = await fetchPayment(orders);
    console.log(payment);
  } catch (err) {
    console.error(err);
  }

}

Node | Event Looping

The Event Loop is the mechanism that allows Node.js (single-threaded) to handle multiple operations concurrently without blocking.

It continuously checks for tasks and executes them in a specific order using queues and phases.



Execution priority:
  1. process.nextTick
  2. Promises (.then)
  3. Then event loop phases
More precise  

  1. Current code execution
  2. process.nextTick queue  (Not part of Event Loop)
  3. Promise (microtask queue, Part of Event Loop, executes between each phase of event loop)
  4. Event loop phases (timers → poll → check → ...)

Why We need Event Loop:

Node.js runs on one main thread, so it cannot do multiple things at the exact same time.

Instead:

  • It offloads heavy work (I/O, network, DB) to OS / libuv
  • Uses the event loop to process completed tasks 
Node.js delegates asynchronous operations to the OS or libuv’s thread pool. Once those operations complete, their callbacks are queued, and the event loop processes and executes them in different phases. This architecture allows Node.js to handle asynchronous operations efficiently despite being single-threaded.

In Layman terms Basically Node outsources operations to libuv thread pool/OS  so they run asynchronously and Event Loop is the place where calls back of those operations handled when they completed or failed, So with the help of Event loops and libuv thread pool//OS Node performs asynchronous operation. 

Event Loop Phases:

  1. Timers
  2. Pending Callbacks
  3. Poll (I/O)
  4. Check
  5. Close Callbacks 

1. Timers: Responsible to execute callbacks of timers event like setTimeout(), setInterval().

Timers phase does NOT “execute timers directly when scheduled.”
It executes callbacks of timers whose delay has already expired.

Example
Step1: When you call  
setTimeout(() => console.log("hi"), 1000);

Node.js does NOT execute it immediately
Instead:

  • Registers the timer with libuv (timer system)
  • Keeps track of when it should expire
Step2:
After ~1000ms:
  • Timer becomes “ready”
  • Its callback is placed in the Timers queue

Step3: 
Event loop enters Timers phase
  • It checks: “Which timers have expired?”
  • Executes their callbacks

setTimeout called

Timer registered (libuv)

Time passes

Timer expires → added to timers queue

Event loop enters Timers phase

Callback executed


Why setTimeout(fn, 0) is NOT immediate?

setTimeout(fn, 0) does not execute immediately because the callback is scheduled and only runs when the event loop reaches the timers phase after the current execution completes.

setTimeout(() => console.log("A"), 0);
console.log("B");

Output 
B
A

Main Thread sends setTimeout(() => console.log("A"), 0); to run with libuv thread pool
Main tread executes console.log("B");
0 milliseconds passed so setTimeout get registered with Timer phase
Now it get executed when execution enters into Event Loop after completing current loop.(As Timers is first stage of Event Loop)

setTimeout and setInterval register timers with the system. Once their delay expires, their callbacks are queued and executed during the Timers phase of the event loop, not immediately.



2. Pending Callbacks:
Pending Callbacks phase handles deferred system-level callbacks from the previous loop,
while Poll phase handles new I/O events and executes most I/O callbacks.

Executes callbacks that were deferred from the previous event loop iteration

Typical cases:
  • Some TCP errors (like ECONNREFUSED)
  • System-level I/O errors
  • Low-level libuv deferred callbacks

These are not your regular fs.readFile or DB call or HTTP callbacks.

Something happened earlier, but couldn’t be processed immediately → now handled here

 Important:

  • Rarely used directly in application code
  • Mostly internal to Node.js
In practice, developers mostly interact with the poll phase, since that's where application-level I/O happens. The pending callbacks phase is more of an internal mechanism for handling edge-case system callbacks.


3. Poll Phase: Most important phase of Event Loop 

This is the main I/O execution phase.
Mostly all developer written code execute (or handled callbacks) from here.

Poll Phase = Heart of Node.js
Handles most I/O (API calls, DB, file system)

Handle incoming I/O and keep the app running.

Responsibilities: 
  1. Execute I/O callbacks: 
    • File system (fs.readFile) 
    • Network (HTTP, DB calls) 
  2. Wait for new I/O events if none are ready

Example

  1. You call fs.readFile() or any DB call or any API call
  2. OS processes it
  3. Result comes back

Callback runs in Poll phase


4. Check Phase

Runs after Poll phase

Executes: setImmediate()


5. Close Callbacks

The Close Callbacks phase executes callbacks related to resource cleanup, especially when a handle (like a socket or stream) is closed.

When something like:

  • a socket
  • a stream
  • a connection

gets closed or destroyed, its cleanup callback runs here.

Executes: socket.on('close'), cleanup tasks


Node | Promise

A Promise is an object that represents the eventual result (success or failure) of an asynchronous operation.

Think of it as a placeholder for a value that will be available later.

 Ordering food online:

  • You place an order → Promise created
  • Food arrives → Resolved
  • Order cancelled → Rejected

Promise States

A Promise has 3 states:

  1. Pending → initial state
  2. Fulfilled → operation successful
  3. Rejected → operation failed

promise
.then(result => console.log(result)) // success
.catch(error => console.log(error)); // failure

Callback Hell Problem

Before Promise:

doSomething(() => {
doSomethingElse(() => {
doAnotherThing(() => {
// messy
});
});
});

After Promise: Clean & readable
doSomething()
.then(doSomethingElse)
.then(doAnotherThing)
.catch(console.error);


How Promises Work Internally (Important)

When resolved/rejected:

  • They don’t execute immediately
  • They go to Microtask Queue

Event loop executes them:

  • After process.nextTick
  • Before timers / I/O


Async/Await (Modern Way)

Built on top of Promises

async function run() {
try {
const result = await promise;
console.log(result);
} catch (err) {
console.log(err);
}
}


Chaining

fetchData()
.then(data => process(data))
.then(result => save(result));



Error Handling

promise
.then(data => { throw new Error("fail"); })
.catch(err => console.log(err));


Event Loop Context

setTimeout(() => console.log("timeout"), 0);
Promise.resolve().then(() => console.log("promise"));


Static Methods
  • Promise.all() → parallel execution (fails fast)
  • Promise.allSettled() → waits for all
  • Promise.race() → first result wins
  • Promise.any() → first success

A Promise in JavaScript is an object that represents the eventual completion
or failure of an asynchronous operation. It allows handling async results
using .then, .catch, or async/await, and internally it uses the microtask queue
for execution.

Wednesday, April 22, 2026

Node | Execution order

What could be execution order

Case1: Code in main module (Normal case)

  • setTimeout(() => console.log("timeout"), 0);
  • setImmediate(() => console.log("immediate"));
  • Promise.resolve().then(() => console.log("promise"));
  • process.nextTick(() => console.log("nextTick"));
Output:
  1. nextTick
  2. promise
  3. timeout
  4. immediate

Explanation:

Microtasks run after every phase, before moving to next phase.
Microtasks are executed immediately after the current operation, before the event loop proceeds to the next phase

Execution priority:
  1. process.nextTick
  2. Promises (.then)
  3. Then event loop phases

  • nextTick will go in process.nextTick() queue
  • Promise will go in Promise microtask queue

Based on above given priority nextTick priority next click is always on top and then promise.
  1. process.nextTick (nextTick)
  2. Promises (.then)  (Promise)
  3. Event Loop (setimmediate, settimeout, setinterval)
Event loop phases in order
1. Timers
2. Pending Callbacks
3. Idle, Prepare (internal)
4. Poll (MOST IMPORTANT)
5. Check
6. Close Callbacks

settimeout, setinterval executes in Timers phase 
Setimmediate executes in Check phase 

In event loop first phase is Timers so timeout will execute first then setimmediate in Check phase.

This is how below order comes in output
  1. nextTick
  2. promise
  3. timeout
  4. immediate
                                                  ==========================

Case2: The callback runs inside the Poll phase (I/O phase)8 (Special case)

const fs = require("fs");

fs.readFile(__filename, () => {
setTimeout(() => console.log("timeout"), 0);
setImmediate(() => console.log("immediate"));
Promise.resolve().then(() => console.log("promise"));
process.nextTick(() => console.log("nextTick"));
});

Output:
  1. nextTick
  2. promise
  3. immediate
  4. timeout
immediate and timeout sequence changed compare to normal case  

Explanation:

Above code will run inside  the Poll phase (I/O phase) because its I/O file read operation.
All I/O operations/API calls goes in Poll phase 

Inside that callback, we schedule:

APIGoes to
setTimeoutTimers queue
setImmediateCheck queue
Promise.thenMicrotask queue
process.nextTickNextTick queue

nextTick registers in process.nextTick() queue
Promise registers in Promise microtask queue
  • next click is top priority so its at no.1
  • microtask queue executed between each phase of Event Loop. currently execution is at poll phase as execution move to next phase first it will check and execute if anything in microtask queue, so Promise is at no.2
  • next phase of event loop is check phase in which immediate get registered, so immediate is at no.3
  • Execution finishes this cycle an re-iterate next cycle, in next cycle first phase is Timers, so timeout is at no.4

Node | process.nextclick

process.nextTick() schedules a callback to run immediately after the current operation , before the event loop continues . It runs: Befor...