Skip to main content

Async Programming

📌 21. What are callbacks in Node.js, and what is callback hell?​

Callback āĻšāϞ⧋ āĻāĻŽāύ āĻāĻ•āϟāĻŋ function āϝ⧇āϟāĻžāϕ⧇ argument āĻšāĻŋāϏ⧇āĻŦ⧇ āĻ…āĻ¨ā§āϝ āĻāĻ•āϟāĻŋ function-āĻ pass āĻ•āϰāĻž āĻšāϝāĻŧ, āĻāĻŦāĻ‚ āϏ⧇āχ function āϤāĻžāϰ āĻ•āĻžāϜ āĻļ⧇āώ āĻ•āϰāĻžāϰ āĻĒāϰ⧇ āĻāϟāĻŋāϕ⧇ execute āĻ•āϰ⧇āĨ¤ Node.js-āĻ āϝ⧇āĻšā§‡āϤ⧁ āϏāĻŦāĻ•āĻŋāϛ⧁ asynchronous āĻāĻŦāĻ‚ non-blocking, āϤāĻžāχ callback āĻšāϞ⧋ asynchronous operations handle āĻ•āϰāĻžāϰ āϏāĻŦāĻšā§‡āϝāĻŧ⧇ āĻĒ⧁āϰāύ⧋ āĻāĻŦāĻ‚ āĻŽā§ŒāϞāĻŋāĻ• āĻĒāĻĻā§āϧāϤāĻŋāĨ¤

// āϏāĻšāϜ callback-āĻāϰ āωāĻĻāĻžāĻšāϰāĻŖ
fs.readFile("file.txt", "utf8", function (err, data) {
console.log(data);
});

Callback Hell āϕ⧀?

āϝāĻ–āύ āĻāĻ•āϟāĻŋ asynchronous operation-āĻāϰ āĻĒāϰ⧇ āφāϰ⧇āĻ•āϟāĻŋ, āϤāĻžāϰāĻĒāϰ⧇ āφāϰ⧇āĻ•āϟāĻŋ — āĻāĻ­āĻžāĻŦ⧇ nested callbacks-āĻāϰ āĻ¸ā§āϤāϰ āĻŦāĻžāĻĄāĻŧāϤ⧇ āĻĨāĻžāϕ⧇, āϤāĻ–āύ code āĻĻ⧇āĻ–āϤ⧇ āĻāĻ•āϟāĻŋ āĻ¤ā§āϰāĻŋāϭ⧁āĻœā§‡āϰ āĻŽāϤ⧋ āĻĄāĻžāύāĻĻāĻŋāϕ⧇ āĻšā§‡āϞ⧇ āϝāĻžāϝāĻŧāĨ¤ āĻāϟāĻžāϕ⧇āχ Callback Hell āĻŦāĻž Pyramid of Doom āĻŦāϞāĻž āĻšāϝāĻŧāĨ¤

// Callback Hell-āĻāϰ āωāĻĻāĻžāĻšāϰāĻŖ
getUser(userId, function (err, user) {
getOrders(user.id, function (err, orders) {
getOrderDetails(orders[0].id, function (err, details) {
sendEmail(details, function (err, result) {
// āφāϰ⧋ nested āĻšāϤ⧇ āĻĨāĻžāϕ⧇...
});
});
});
});

āĻāϤ⧇ code āĻĒāĻĄāĻŧāĻž, maintain āĻ•āϰāĻž āĻāĻŦāĻ‚ debug āĻ•āϰāĻž āĻ…āĻ¤ā§āϝāĻ¨ā§āϤ āĻ•āĻ āĻŋāύ āĻšāϝāĻŧ⧇ āĻĒāĻĄāĻŧ⧇āĨ¤


💡 How do you avoid callback hell using Promises or async/await?​

ā§§. Promises āĻĻāĻŋāϝāĻŧ⧇

Promise āĻšāϞ⧋ āĻāĻ•āϟāĻŋ object āϝ⧇āϟāĻŋ āĻāĻ•āϟāĻŋ asynchronous operation-āĻāϰ eventual completion āĻŦāĻž failure-āϕ⧇ represent āĻ•āϰ⧇āĨ¤ āĻāϟāĻŋāϰ āϤāĻŋāύāϟāĻŋ state āĻĨāĻžāϕ⧇: pending, fulfilled, āĻāĻŦāĻ‚ rejectedāĨ¤

// Promise chain āĻĻāĻŋāϝāĻŧ⧇ Callback Hell āĻāĻĄāĻŧāĻžāύ⧋
getUser(userId)
.then((user) => getOrders(user.id))
.then((orders) => getOrderDetails(orders[0].id))
.then((details) => sendEmail(details))
.catch((err) => console.error(err)); // centralized error handling

āĻāϤ⧇ code flat āĻĨāĻžāϕ⧇ āĻāĻŦāĻ‚ āĻĒāĻĄāĻŧāϤ⧇ āϏāĻšāϜ āĻšāϝāĻŧāĨ¤

⧍. async/await āĻĻāĻŋāϝāĻŧ⧇

async/await āĻšāϞ⧋ Promises-āĻāϰāχ syntactic sugar, āϝāĻž asynchronous code-āϕ⧇ synchronous-āĻāϰ āĻŽāϤ⧋ āĻĻ⧇āĻ–āϤ⧇ āĻāĻŦāĻ‚ āĻĒāĻĄāĻŧāϤ⧇ āϏāĻžāĻšāĻžāĻ¯ā§āϝ āĻ•āϰ⧇āĨ¤

// async/await āĻĻāĻŋāϝāĻŧ⧇
async function processOrder(userId) {
try {
const user = await getUser(userId);
const orders = await getOrders(user.id);
const details = await getOrderDetails(orders[0].id);
const result = await sendEmail(details);
return result;
} catch (err) {
console.error("Error:", err);
}
}

async keyword āĻĻāĻŋāϝāĻŧ⧇ function declare āĻ•āϰāϤ⧇ āĻšāϝāĻŧ, āĻāĻŦāĻ‚ await keyword āĻĻāĻŋāϝāĻŧ⧇ Promise resolve āĻšāĻ“āϝāĻŧāĻž āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āĻ…āĻĒ⧇āĻ•ā§āώāĻž āĻ•āϰāĻž āĻšāϝāĻŧāĨ¤ try/catch block āĻĻāĻŋāϝāĻŧ⧇ error handle āĻ•āϰāĻž āĻšāϝāĻŧāĨ¤


âš™ī¸ What is the error-first callback convention and why is it used?​

Error-First Callback (āĻŦāĻž Node.js Callback Convention) āĻšāϞ⧋ āĻāĻ•āϟāĻŋ standard pattern āϝ⧇āĻ–āĻžāύ⧇ callback function-āĻāϰ āĻĒā§āϰāĻĨāĻŽ parameter āϏāĻŦāϏāĻŽāϝāĻŧ error āĻāĻŦāĻ‚ āĻĻā§āĻŦāĻŋāϤ⧀āϝāĻŧ parameter āĻšāϞ⧋ successful resultāĨ¤

// Error-first callback convention
fs.readFile("file.txt", "utf8", function (err, data) {
if (err) {
// āĻĒā§āϰāĻĨāĻŽā§‡ āϏāĻŦāϏāĻŽāϝāĻŧ error check āĻ•āϰāϤ⧇ āĻšāĻŦ⧇
console.error("File āĻĒāĻĄāĻŧāϤ⧇ āϏāĻŽāĻ¸ā§āϝāĻž āĻšāϝāĻŧ⧇āϛ⧇:", err);
return;
}
// error āύāĻž āĻĨāĻžāĻ•āϞ⧇ data āύāĻŋāϝāĻŧ⧇ āĻ•āĻžāϜ āĻ•āϰ⧋
console.log(data);
});

āϕ⧇āύ āĻāχ convention āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āĻšāϝāĻŧ:

  • Consistency: Node.js-āĻāϰ āϏāĻŦ built-in modules (āϝ⧇āĻŽāύ fs, http, crypto) āĻāχ pattern follow āĻ•āϰ⧇, āĻĢāϞ⧇ developer-āϰāĻž āϏāĻšāĻœā§‡āχ āϝ⧇āϕ⧋āύ⧋ library-āϰ āϏāĻžāĻĨ⧇ āĻ•āĻžāϜ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤
  • Explicit Error Handling: Error āϏāĻŦāϏāĻŽāϝāĻŧ āĻĒā§āϰāĻĨāĻŽā§‡ āφāϏ⧇ āĻŦāϞ⧇ developer-āϰāĻž āĻāϟāĻžāϕ⧇ ignore āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ āύāĻž — error check āĻ•āϰāĻžāϟāĻž mandatory āĻšāϝāĻŧ⧇ āϝāĻžāϝāĻŧāĨ¤
  • Predictability: āϏāĻŦ asynchronous function āĻāĻ•āχ āϧāϰāύ⧇āϰ signature follow āĻ•āϰāĻžāϝāĻŧ code predictable āĻāĻŦāĻ‚ maintainable āĻĨāĻžāϕ⧇āĨ¤

❓ What is inversion of control?​

🔄 How do you convert a callback-based library to Promises using util.promisify?​

Node.js-āĻāϰ built-in util module-āĻ promisify function āφāϛ⧇, āϝ⧇āϟāĻŋ error-first callback convention follow āĻ•āϰāĻž āϝ⧇āϕ⧋āύ⧋ function-āϕ⧇ automatically Promise-based function-āĻ āϰ⧂āĻĒāĻžāĻ¨ā§āϤāϰ āĻ•āϰ⧇āĨ¤

const util = require("util");
const fs = require("fs");

// fs.readFile āĻāĻ•āϟāĻŋ callback-based function
// promisify āĻĻāĻŋāϝāĻŧ⧇ āĻāϟāĻŋāϕ⧇ Promise-based āĻŦāĻžāύāĻžāύ⧋ āĻšāĻšā§āϛ⧇
const readFileAsync = util.promisify(fs.readFile);

// āĻāĻ–āύ āĻāϟāĻžāϕ⧇ async/await āĻĻāĻŋāϝāĻŧ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝāĻžāĻŦ⧇
async function readConfig() {
try {
const data = await readFileAsync("config.json", "utf8");
const config = JSON.parse(data);
console.log(config);
} catch (err) {
console.error("Config āĻĒāĻĄāĻŧāϤ⧇ āϏāĻŽāĻ¸ā§āϝāĻž:", err);
}
}

Custom Callback function promisify āĻ•āϰāĻž:

// āύāĻŋāĻœā§‡āϰ āϤ⧈āϰāĻŋ callback-based function
function delay(ms, callback) {
setTimeout(() => callback(null, `${ms}ms āĻĒāϰ⧇ āϏāĻŽā§āĻĒāĻ¨ā§āύ`), ms);
}

// promisify āĻĻāĻŋāϝāĻŧ⧇ convert āĻ•āϰāĻž
const delayAsync = util.promisify(delay);

// āĻāĻ–āύ Promise āĻšāĻŋāϏ⧇āĻŦ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝāĻžāĻŦ⧇
delayAsync(2000).then((msg) => console.log(msg));

āϗ⧁āϰ⧁āĻ¤ā§āĻŦāĻĒā§‚āĻ°ā§āĻŖ āύ⧋āϟ: util.promisify āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ error-first callback convention follow āĻ•āϰāĻž functions-āĻ āĻ•āĻžāϜ āĻ•āϰ⧇āĨ¤ āϝāĻĻāĻŋ āϕ⧋āύ⧋ library āĻ­āĻŋāĻ¨ā§āύ pattern āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇, āϤāĻžāĻšāϞ⧇ manually Promise wrap āĻ•āϰāϤ⧇ āĻšāĻŦ⧇āĨ¤

📌 22. What are Promises in Node.js, and how do they work?​

Promise āĻšāϞ⧋ āĻāĻ•āϟāĻŋ object āϝ⧇āϟāĻŋ āĻāĻ•āϟāĻŋ asynchronous operation-āĻāϰ āĻ­āĻŦāĻŋāĻˇā§āĻ¯ā§Ž completion āĻŦāĻž failure-āϕ⧇ represent āĻ•āϰ⧇āĨ¤ āϏāĻšāϜ āĻ­āĻžāώāĻžāϝāĻŧ, āĻāϟāĻŋ āĻāĻ•āϟāĻŋ "āĻĒā§āϰāϤāĻŋāĻļā§āϰ⧁āϤāĻŋ" — āĻšāϝāĻŧ āĻ•āĻžāϜāϟāĻŋ āϏāĻĢāϞāĻ­āĻžāĻŦ⧇ āĻļ⧇āώ āĻšāĻŦ⧇, āύāϝāĻŧāϤ⧋ āϕ⧋āύ⧋ error āĻĻ⧇āĻŦ⧇āĨ¤

Promise-āĻāϰ āϤāĻŋāύāϟāĻŋ State

pending  ──→  fulfilled (resolve āĻšāϝāĻŧ⧇āϛ⧇)
──→ rejected (error āĻšāϝāĻŧ⧇āϛ⧇)

āĻāĻ•āϟāĻŋ Promise āĻāĻ•āĻŦāĻžāϰ fulfilled āĻŦāĻž rejected āĻšāϞ⧇ āϏ⧇āϟāĻŋ āφāϰ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ āĻšāϝāĻŧ āύāĻž — āĻāχ property-āϕ⧇ āĻŦāϞ⧇ immutabilityāĨ¤

Promise āϕ⧀āĻ­āĻžāĻŦ⧇ āϤ⧈āϰāĻŋ āĻ•āϰāϤ⧇ āĻšāϝāĻŧ

const myPromise = new Promise((resolve, reject) => {
const success = true;

if (success) {
resolve("āĻ•āĻžāϜ āϏāĻĢāϞ āĻšāϝāĻŧ⧇āϛ⧇!"); // fulfilled state-āĻ āύāĻŋāϝāĻŧ⧇ āϝāĻžāϝāĻŧ
} else {
reject(new Error("āĻ•āĻžāϜ āĻŦā§āϝāĻ°ā§āĻĨ āĻšāϝāĻŧ⧇āϛ⧇!")); // rejected state-āĻ āύāĻŋāϝāĻŧ⧇ āϝāĻžāϝāĻŧ
}
});

// Promise consume āĻ•āϰāĻž
myPromise
.then((result) => console.log(result)) // fulfilled āĻšāϞ⧇
.catch((err) => console.error(err)); // rejected āĻšāϞ⧇

Promise.all, Promise.race, Promise.allSettled

āĻāĻ•āϏāĻžāĻĨ⧇ āĻāĻ•āĻžāϧāĻŋāĻ• Promise handle āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āĻāχ static methods āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āĻšāϝāĻŧ:

const p1 = fetch("/api/users");
const p2 = fetch("/api/orders");
const p3 = fetch("/api/products");

// āϏāĻŦāϗ⧁āϞ⧋ āϏāĻĢāϞ āĻšāϞ⧇āχ result āĻĻ⧇āĻŦ⧇, āĻāĻ•āϟāĻŋ fail āĻ•āϰāϞ⧇āχ reject āĻšāĻŦ⧇
Promise.all([p1, p2, p3])
.then(([users, orders, products]) => {
console.log(users, orders, products);
})
.catch((err) => console.error("āϝ⧇āϕ⧋āύ⧋ āĻāĻ•āϟāĻŋ fail āĻ•āϰ⧇āϛ⧇:", err));

// āϏāĻŦāĻšā§‡āϝāĻŧ⧇ āφāϗ⧇ āϝ⧇āϟāĻŋ resolve/reject āĻšāĻŦ⧇ āϏ⧇āϟāĻŋāχ return āĻ•āϰāĻŦ⧇
Promise.race([p1, p2, p3]).then((fastest) =>
console.log("āϏāĻŦāĻšā§‡āϝāĻŧ⧇ āĻĻā§āϰ⧁āϤ:", fastest),
);

// āϏāĻŦ Promise āĻļ⧇āώ āĻšāĻ“āϝāĻŧāĻžāϰ āĻĒāϰ⧇ āĻĒā§āϰāϤāĻŋāϟāĻŋāϰ status āϜāĻžāύāĻžāĻŦ⧇ (fail āĻšāϞ⧇āĻ“)
Promise.allSettled([p1, p2, p3]).then((results) => {
results.forEach((result) => {
if (result.status === "fulfilled") {
console.log("āϏāĻĢāϞ:", result.value);
} else {
console.log("āĻŦā§āϝāĻ°ā§āĻĨ:", result.reason);
}
});
});

🔗 Related Questions
  • What are the states of a Promise?
  • What is Promise chaining and what are its pitfalls?

Promise chaining āĻšāϞ⧋ āĻāĻ•āϟāĻŋāϰ āĻĒāϰ āĻāĻ•āϟāĻŋ .then() āϜ⧁āĻĄāĻŧ⧇ āĻĻāĻŋāϝāĻŧ⧇ sequential asynchronous operations āϚāĻžāϞāĻžāύ⧋āϰ techniqueāĨ¤ āĻĒā§āϰāϤāĻŋāϟāĻŋ .then() āĻāĻ•āϟāĻŋ āύāϤ⧁āύ Promise return āĻ•āϰ⧇āĨ¤

āϏāĻ āĻŋāĻ• Promise Chaining

getUserFromDB(userId)
.then((user) => {
console.log("User āĻĒāĻžāĻ“āϝāĻŧāĻž āϗ⧇āϛ⧇:", user.name);
return getOrdersByUser(user.id); // āύāϤ⧁āύ Promise return āĻ•āϰāϤ⧇ āĻšāĻŦ⧇
})
.then((orders) => {
console.log("Orders:", orders.length);
return getOrderDetails(orders[0].id);
})
.then((details) => {
console.log("Details:", details);
})
.catch((err) => {
// chain-āĻāϰ āϝ⧇āϕ⧋āύ⧋ āϜāĻžāϝāĻŧāĻ—āĻžāϝāĻŧ error āĻšāϞ⧇ āĻāĻ–āĻžāύ⧇ āφāϏāĻŦ⧇
console.error("āϕ⧋āĻĨāĻžāĻ“ āϏāĻŽāĻ¸ā§āϝāĻž āĻšāϝāĻŧ⧇āϛ⧇:", err);
})
.finally(() => {
// āϏāĻĢāϞ āĻŦāĻž āĻŦā§āϝāĻ°ā§āĻĨ — āϏāĻŦāϏāĻŽāϝāĻŧ āĻāϟāĻŋ āϚāϞāĻŦ⧇ (cleanup-āĻāϰ āϜāĻ¨ā§āϝ)
db.connection.close();
});

Promise Chaining-āĻāϰ Pitfalls

Pitfall ā§§: .then()-āĻāϰ āϭ⧇āϤāϰ⧇ return āύāĻž āĻ•āϰāĻž

// ❌ āϭ⧁āϞ — return āύāĻž āĻ•āϰāĻžāϝāĻŧ chain āϭ⧇āϙ⧇ āϝāĻžāϝāĻŧ
getUserFromDB(userId)
.then((user) => {
getOrdersByUser(user.id); // return āύ⧇āχ! āĻĒāϰ⧇āϰ .then() undefined āĻĒāĻžāĻŦ⧇
})
.then((orders) => {
console.log(orders); // undefined āφāϏāĻŦ⧇
});

// ✅ āϏāĻ āĻŋāĻ•
getUserFromDB(userId)
.then((user) => {
return getOrdersByUser(user.id); // āĻ…āĻŦāĻļā§āϝāχ return āĻ•āϰāϤ⧇ āĻšāĻŦ⧇
})
.then((orders) => {
console.log(orders); // āϏāĻ āĻŋāĻ• data āφāϏāĻŦ⧇
});

Pitfall ⧍: Nested Promise āϤ⧈āϰāĻŋ āĻ•āϰāĻž (Promise Hell)

// ❌ āϭ⧁āϞ — āφāĻŦāĻžāϰ callback hell-āĻāϰ āĻŽāϤ⧋ nested āĻšāϝāĻŧ⧇ āϝāĻžāĻšā§āϛ⧇
getUserFromDB(userId).then((user) => {
return getOrdersByUser(user.id).then((orders) => {
// āĻāĻ–āĻžāύ⧇ nest āύāĻž āĻ•āϰ⧇
return getOrderDetails(orders[0].id).then((details) => details); // flat chain āĻ•āϰāĻž āωāϚāĻŋāϤ āĻ›āĻŋāϞ
});
});

// ✅ āϏāĻ āĻŋāĻ• — flat chain
getUserFromDB(userId)
.then((user) => getOrdersByUser(user.id))
.then((orders) => getOrderDetails(orders[0].id))
.then((details) => console.log(details));

Pitfall ā§Š: āĻĒā§āϰāϤāĻŋāϟāĻŋ .then()-āĻ āφāϞāĻžāĻĻāĻž .catch() āύāĻž āϰāĻžāĻ–āĻž

// ❌ āϭ⧁āϞ — āĻļ⧁āϧ⧁ āĻļ⧇āώ⧇ āĻāĻ•āϟāĻŋ .catch() āĻĨāĻžāĻ•āϞ⧇ āϕ⧋āĻĨāĻžāϝāĻŧ error āĻšāϝāĻŧ⧇āϛ⧇ āĻŦā§‹āĻāĻž āϝāĻžāϝāĻŧ āύāĻž
step1()
.then(() => step2())
.then(() => step3())
.catch((err) => console.error(err)); // āϕ⧋āύ step-āĻ āĻšāϞ⧋?

// ✅ āϏāĻ āĻŋāĻ• — specific error handling
step1()
.then(() => step2())
.catch((err) => {
console.error("step2-āĻ āϏāĻŽāĻ¸ā§āϝāĻž:", err);
throw err; // re-throw āĻ•āϰ⧇ āĻĒāϰ⧇āϰ .catch()-āĻāĻ“ āĻĒāĻžāĻ āĻžāύ⧋ āϝāĻžāϝāĻŧ
})
.then(() => step3())
.catch((err) => console.error("step3-āĻ āϏāĻŽāĻ¸ā§āϝāĻž:", err));

Pitfall ā§Ē: .catch() āĻ›āĻžāĻĄāĻŧāĻžāχ chain āĻļ⧇āώ āĻ•āϰāĻž

// ❌ āĻŦāĻŋāĻĒāĻœā§āϜāύāĻ• — unhandled rejection āĻšāĻŦ⧇
getUserFromDB(userId).then((user) => processUser(user));
// .catch() āύ⧇āχ!

// ✅ āϏāĻŦāϏāĻŽāϝāĻŧ .catch() āĻĻāĻŋāϝāĻŧ⧇ āĻļ⧇āώ āĻ•āϰ⧋
getUserFromDB(userId)
.then((user) => processUser(user))
.catch((err) => console.error("Error:", err));

Pitfall ā§Ģ: async/await-āĻāϰ āϏāĻžāĻĨ⧇ mix āĻ•āϰāĻž

// ❌ āĻ…āĻĒā§āϰāϝāĻŧā§‹āϜāύ⧀āϝāĻŧ mix — confusing āĻšāϝāĻŧ
async function fetchData() {
return getUserFromDB(userId).then((user) => {
// async function-āĻ .then() āĻŦā§āϝāĻŦāĻšāĻžāϰ āύāĻž āĻ•āϰāĻžāχ āĻ­āĻžāϞ⧋
return user;
});
}

// ✅ āĻĒāϰāĻŋāĻˇā§āĻ•āĻžāϰ — āĻļ⧁āϧ⧁ async/await āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧋
async function fetchData() {
const user = await getUserFromDB(userId);
return user;
}
āĻŦāĻŋāώāϝāĻŧāĻŽā§‚āϞ āĻ•āĻĨāĻž
PromiseAsynchronous operation-āĻāϰ future result represent āĻ•āϰ⧇
Statespending → fulfilled āĻ…āĻĨāĻŦāĻž rejected
Global Rejectionprocess.on('unhandledRejection') āĻĻāĻŋāϝāĻŧ⧇ handle āĻ•āϰāϤ⧇ āĻšāϝāĻŧ
ChainingāĻĒā§āϰāϤāĻŋāϟāĻŋ .then()-āĻ āĻ…āĻŦāĻļā§āϝāχ return āĻ•āϰāϤ⧇ āĻšāĻŦ⧇
āϏāĻŦāĻšā§‡āϝāĻŧ⧇ āĻŦāĻĄāĻŧ pitfallreturn āύāĻž āĻ•āϰāĻž āĻāĻŦāĻ‚ .catch() āύāĻž āϰāĻžāĻ–āĻž

🚨 How are errors propagated in Promise chains?​

🔗 Related Questions
  • What is the difference between Promise.resolve() and new Promise(resolve => resolve())?
  • How do you handle Promise rejections globally?

āϝāĻĻāĻŋ āϕ⧋āύ⧋ Promise reject āĻšāϝāĻŧ āĻāĻŦāĻ‚ āϏ⧇āĻ–āĻžāύ⧇ .catch() āύāĻž āĻĨāĻžāϕ⧇, āϏ⧇āϟāĻŋ unhandled rejection āĻšāϝāĻŧāĨ¤ Production-āĻ āĻāϟāĻŋ āϖ⧁āĻŦāχ āĻŦāĻŋāĻĒāĻœā§āϜāύāĻ• āĻ•āĻžāϰāĻŖ error āύ⧀āϰāĻŦ⧇ āĻšāĻžāϰāĻŋāϝāĻŧ⧇ āϝāĻžāϝāĻŧāĨ¤

unhandledRejection Event

// process-āĻāϰ āωāĻĒāϰ⧇ global handler āĻŦāϏāĻžāύ⧋
process.on("unhandledRejection", (reason, promise) => {
console.error("Unhandled Promise Rejection āϧāϰāĻž āĻĒāĻĄāĻŧ⧇āϛ⧇!");
console.error("Reason:", reason);
console.error("Promise:", promise);

// Production-āĻ application gracefully āĻŦāĻ¨ā§āϧ āĻ•āϰāĻž āωāϚāĻŋāϤ
process.exit(1);
});

// āĻāĻ–āύ .catch() āĻ›āĻžāĻĄāĻŧāĻž reject āĻšāϞ⧇āĻ“ āωāĻĒāϰ⧇āϰ handler āĻ•āĻžāϜ āĻ•āϰāĻŦ⧇
Promise.reject(new Error("āĻāχ error āϕ⧇āω catch āĻ•āϰ⧇āύāĻŋ!"));

rejectionHandled Event

// āϝāĻ–āύ āφāϗ⧇āϰ unhandled rejection āĻĒāϰ⧇ catch āĻ•āϰāĻž āĻšāϝāĻŧ
process.on("rejectionHandled", (promise) => {
console.warn("āĻāĻ•āϟāĻŋ rejection āĻĻ⧇āϰāĻŋāϤ⧇ handle āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇:", promise);
});

Express.js-āĻ Global Error Handling

// Async route handler-āĻ unhandled rejection āϧāϰāĻž
const asyncHandler = (fn) => (req, res, next) => {
Promise.resolve(fn(req, res, next)).catch(next);
};

// āĻŦā§āϝāĻŦāĻšāĻžāϰ
app.get(
"/users",
asyncHandler(async (req, res) => {
const users = await getUsersFromDB(); // error āĻšāϞ⧇ automatically next(err) āϝāĻžāĻŦ⧇
res.json(users);
}),
);

// Global error middleware
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ message: "Internal Server Error" });
});

Node.js v15+ āĻĨ⧇āϕ⧇: Unhandled Promise rejection āĻšāϞ⧇ Node.js automatically process crash āĻ•āϰ⧇āĨ¤ āϤāĻžāχ unhandledRejection handler āϰāĻžāĻ–āĻž production-āĻ āĻ…āĻĒāϰāĻŋāĻšāĻžāĻ°ā§āϝāĨ¤


📌 23. What is async/await, and how does it simplify asynchronous code?​

async/await āĻšāϞ⧋ JavaScript-āĻāϰ āĻāĻ•āϟāĻŋ syntax āϝāĻž Promise-based asynchronous code āϕ⧇ synchronous code-āĻāϰ āĻŽāϤ⧋ āĻĻ⧇āĻ–āϤ⧇ āĻ“ āĻĒāĻĄāĻŧāϤ⧇ āϏāĻžāĻšāĻžāĻ¯ā§āϝ āĻ•āϰ⧇āĨ¤

  • async keyword āĻĻāĻŋāϝāĻŧ⧇ āĻāĻ•āϟāĻŋ function declare āĻ•āϰāϞ⧇ āϏ⧇āϟāĻŋ āϏāĻŦāϏāĻŽāϝāĻŧ āĻāĻ•āϟāĻŋ Promise return āĻ•āϰ⧇āĨ¤
  • await keyword āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ async function-āĻāϰ āϭ⧇āϤāϰ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝāĻžāϝāĻŧāĨ¤ āĻāϟāĻŋ āĻāĻ•āϟāĻŋ Promise resolve āĻšāĻ“āϝāĻŧāĻž āĻĒāĻ°ā§āϝāĻ¨ā§āϤ execution pause āĻ•āϰ⧇ āϰāĻžāϖ⧇ āĻāĻŦāĻ‚ resolved value āϟāĻŋ return āĻ•āϰ⧇āĨ¤

āφāϗ⧇ Promise chain āĻĻāĻŋāϝāĻŧ⧇ āϞāĻŋāĻ–āϤ⧇ āĻšāϤ⧋:

fetch("/api/user")
.then((res) => res.json())
.then((data) => console.log(data))
.catch((err) => console.error(err));

async/await āĻĻāĻŋāϝāĻŧ⧇ āĻāĻ•āχ āĻ•āĻžāϜ āĻ…āύ⧇āĻ• āĻĒāϰāĻŋāĻˇā§āĻ•āĻžāϰāĻ­āĻžāĻŦ⧇ āϞ⧇āĻ–āĻž āϝāĻžāϝāĻŧ:

async function getUser() {
const res = await fetch("/api/user");
const data = await res.json();
console.log(data);
}

async/await āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϞ⧇ callback hell āĻŦāĻž .then() chain āĻāϰ āϜāϟāĻŋāϞāϤāĻž āĻāĻĄāĻŧāĻžāύ⧋ āϝāĻžāϝāĻŧ āĻāĻŦāĻ‚ code āĻĒāĻĄāĻŧāĻž āĻ“ maintain āĻ•āϰāĻž āϏāĻšāϜ āĻšāϝāĻŧāĨ¤


â¸ī¸ How does await pause execution?​

🔗 Related Questions
  • Is async/await blocking or non-blocking?
  • How does it work under the hood (Promises)?
  • How do you handle errors in async/await using try/catch?

async/await-āĻ error handle āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ standard try/catch block āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āĻšāϝāĻŧāĨ¤ āϝāĻĻāĻŋ await āĻ•āϰāĻž āϕ⧋āύ⧋ Promise reject āĻšāϝāĻŧ, āϤāĻžāĻšāϞ⧇ āϏ⧇āϟāĻŋ automatically catch block-āĻ āϚāϞ⧇ āϝāĻžāϝāĻŧāĨ¤

async function getUser() {
try {
const res = await fetch("/api/user");
const data = await res.json();
console.log(data);
} catch (error) {
// Promise reject āĻšāϞ⧇ āĻŦāĻž āϕ⧋āύ⧋ runtime error āĻšāϞ⧇ āĻāĻ–āĻžāύ⧇ āφāϏāĻŦ⧇
console.error("Error:", error.message);
} finally {
// āϏāĻŦāϏāĻŽāϝāĻŧ execute āĻšāĻŦ⧇ (optional)
console.log("Request complete");
}
}

āĻāĻ•āĻžāϧāĻŋāĻ• await call āĻĨāĻžāĻ•āϞ⧇ āϝ⧇āϕ⧋āύ⧋ āĻāĻ•āϟāĻŋāϤ⧇ error āĻšāϞ⧇ āϏ⧇āϟāĻŋ āĻāĻ•āχ catch block āϧāϰ⧇ āĻĢ⧇āϞāĻŦ⧇, āϝāĻž .then().catch() chain-āĻāϰ āĻšā§‡āϝāĻŧ⧇ āĻ…āύ⧇āĻ• āĻŦ⧇āĻļāĻŋ āϏ⧁āĻŦāĻŋāϧāĻžāϜāύāĻ•āĨ¤


🤔 What happens if you forget the await keyword before a Promise?​

await āϭ⧁āϞ⧇ āϗ⧇āϞ⧇ function āϟāĻŋ Promise resolve āĻšāĻ“āϝāĻŧāĻžāϰ āϜāĻ¨ā§āϝ āĻ…āĻĒ⧇āĻ•ā§āώāĻž āύāĻž āĻ•āϰ⧇ āϏāĻžāĻĨ⧇ āϏāĻžāĻĨ⧇ āĻĒāϰ⧇āϰ line-āĻ āϚāϞ⧇ āϝāĻžāϝāĻŧāĨ¤ āĻĢāϞ⧇ resolved value-āĻāϰ āĻŦāĻĻāϞ⧇ āĻāĻ•āϟāĻŋ pending Promise object āĻĒāĻžāĻ“āϝāĻŧāĻž āϝāĻžāϝāĻŧāĨ¤

async function example() {
const data = fetch("/api/user"); // ❌ await āύ⧇āχ
console.log(data); // Promise { <pending> } — actual data āύāϝāĻŧ
}
async function example() {
const data = await fetch("/api/user"); // ✅ await āφāϛ⧇
console.log(data); // actual Response object
}

āĻāχ āϧāϰāύ⧇āϰ bug āϧāϰāĻž āĻ•āĻ āĻŋāύ āĻšāϤ⧇ āĻĒāĻžāϰ⧇ āĻ•āĻžāϰāĻŖ āϕ⧋āύ⧋ error throw āĻšāϝāĻŧ āύāĻž, āĻ•āĻŋāĻ¨ā§āϤ⧁ program āϭ⧁āϞ result āύāĻŋāϝāĻŧ⧇ āĻ•āĻžāϜ āĻ•āϰāϤ⧇ āĻĨāĻžāϕ⧇āĨ¤


⚡ How do you run multiple async operations in parallel?​

āϝāĻĻāĻŋ āĻāĻ•āϟāĻŋāϰ result-āĻāϰ āωāĻĒāϰ āφāϰ⧇āĻ•āϟāĻŋ āύāĻŋāĻ°ā§āĻ­āϰ āύāĻž āĻ•āϰ⧇, āϤāĻžāĻšāϞ⧇ āϏ⧇āϗ⧁āϞ⧋ āĻāϕ⧇ āĻāϕ⧇ await āĻ•āϰāĻž āωāϚāĻŋāϤ āύāϝāĻŧ — āĻāϤ⧇ āĻ…āĻĒā§āϰāϝāĻŧā§‹āϜāύ⧀āϝāĻŧ āϏāĻŽāϝāĻŧ āύāĻˇā§āϟ āĻšāϝāĻŧāĨ¤ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤ⧇ Promise.all() āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϞ⧇ āϏāĻŦ operation āĻāĻ•āϏāĻžāĻĨ⧇ āĻļ⧁āϰ⧁ āĻšāϝāĻŧ āĻāĻŦāĻ‚ āϏāĻŦāϗ⧁āϞ⧋ āĻļ⧇āώ āĻšāϞ⧇ result āĻĒāĻžāĻ“āϝāĻŧāĻž āϝāĻžāϝāĻŧāĨ¤

❌ Sequential (āϧ⧀āϰ) — āĻāĻ•āϟāĻŋ āĻļ⧇āώ āĻšāϞ⧇ āφāϰ⧇āĻ•āϟāĻŋ āĻļ⧁āϰ⧁ āĻšāϝāĻŧ:

const user = await fetchUser(); // āϧāϰāĻŋ ā§Šā§Ļā§Ļms āϞāĻžāĻ—āϞ⧋
const posts = await fetchPosts(); // āϧāϰāĻŋ āφāϰ⧋ ā§Šā§Ļā§Ļms āϞāĻžāĻ—āϞ⧋
// āĻŽā§‹āϟ ~ā§Ŧā§Ļā§Ļms

✅ Parallel (āĻĻā§āϰ⧁āϤ) — āϏāĻŦāϗ⧁āϞ⧋ āĻāĻ•āϏāĻžāĻĨ⧇ āĻļ⧁āϰ⧁ āĻšāϝāĻŧ:

const [user, posts] = await Promise.all([fetchUser(), fetchPosts()]);
// āĻŽā§‹āϟ ~ā§Šā§Ļā§Ļms (āϝ⧇āϟāĻŋ āϏāĻŦāĻšā§‡āϝāĻŧ⧇ āĻŦ⧇āĻļāĻŋ āϏāĻŽāϝāĻŧ āύ⧇āϝāĻŧ āϏ⧇āϟ⧁āϕ⧁)

âš ī¸ āϏāϤāĻ°ā§āĻ•āϤāĻž: Promise.all() āĻ āϝāĻĻāĻŋ āϝ⧇āϕ⧋āύ⧋ āĻāĻ•āϟāĻŋ Promise reject āĻšāϝāĻŧ, āϤāĻžāĻšāϞ⧇ āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ call āϟāĻŋāχ reject āĻšāϝāĻŧ⧇ āϝāĻžāĻŦ⧇āĨ¤ āϝāĻĻāĻŋ āĻāĻ•āϟāĻŋāϰ failure āĻ…āĻ¨ā§āϝāϗ⧁āϞ⧋āϕ⧇ āĻĒā§āϰāĻ­āĻžāĻŦāĻŋāϤ āĻ•āϰāϤ⧇ āύāĻž āĻĻāĻŋāϤ⧇ āϚāĻžāύ, āϤāĻžāĻšāϞ⧇ Promise.allSettled() āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύ — āĻāϟāĻŋ āϏāĻŦāϗ⧁āϞ⧋āϰ result (fulfilled āĻŦāĻž rejected āϝāĻžāχ āĻšā§‹āĻ•) āφāϞāĻžāĻĻāĻžāĻ­āĻžāĻŦ⧇ āĻĻ⧇āϝāĻŧāĨ¤


📌 24. What is the difference between setTimeout, setInterval, and setImmediate?​

āϤāĻŋāύāϟāĻŋāχ asynchronous code schedule āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āĻŦā§āϝāĻŦāĻšā§ƒāϤ āĻšāϝāĻŧ, āĻ•āĻŋāĻ¨ā§āϤ⧁ āĻāĻĻ⧇āϰ āĻ•āĻžāϜ āĻ•āϰāĻžāϰ āϧāϰāύ āφāϞāĻžāĻĻāĻžāĨ¤

setTimeout(fn, delay) āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āϏāĻŽāϝāĻŧ (millisecond) āĻĒāϰ⧇ callback function āϟāĻŋ āĻāĻ•āĻŦāĻžāϰ execute āĻ•āϰ⧇āĨ¤ delay āĻļ⧇āώ āĻšāϞ⧇ callback āϟāĻŋ event loop-āĻāϰ macrotask queue-āĻ āϝ⧋āĻ— āĻšāϝāĻŧāĨ¤

setTimeout(() => {
console.log("ā§Ģā§Ļā§Ļms āĻĒāϰ⧇ āĻāĻ•āĻŦāĻžāϰ āϚāϞāĻŦ⧇");
}, 500);

setInterval(fn, delay) āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āϏāĻŽāϝāĻŧ āĻĒāϰāĻĒāϰ callback function āϟāĻŋ āĻŦāĻžāϰāĻŦāĻžāϰ execute āĻ•āϰāϤ⧇ āĻĨāĻžāϕ⧇, āϝāϤāĻ•ā§āώāĻŖ āύāĻž clearInterval() āĻĻāĻŋāϝāĻŧ⧇ āĻĨāĻžāĻŽāĻžāύ⧋ āĻšāϝāĻŧāĨ¤

const id = setInterval(() => {
console.log("āĻĒā§āϰāϤāĻŋ ā§§ āϏ⧇āϕ⧇āĻ¨ā§āĻĄā§‡ āϚāϞāĻŦ⧇");
}, 1000);

// āĻĨāĻžāĻŽāĻžāϤ⧇ āĻšāϞ⧇:
clearInterval(id);

setImmediate(fn) (Node.js only) Current event loop iteration-āĻāϰ I/O callback āĻļ⧇āώ āĻšāĻ“āϝāĻŧāĻžāϰ āĻĒāϰāĻĒāϰāχ, āĻ•āĻŋāĻ¨ā§āϤ⧁ setTimeout-āĻāϰ āφāϗ⧇ callback āϟāĻŋ execute āĻ•āϰ⧇āĨ¤ Browser-āĻ āĻāϟāĻŋ available āύ⧇āχāĨ¤

setImmediate(() => {
console.log("I/O phase-āĻāϰ āĻĒāϰāĻĒāϰāχ āϚāϞāĻŦ⧇");
});

āϤāĻŋāύāϟāĻŋāϰ āϤ⧁āϞāύāĻž:

āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝsetTimeoutsetIntervalsetImmediate
āĻ•āϤāĻŦāĻžāϰ āϚāϞ⧇āĻāĻ•āĻŦāĻžāϰāĻŦāĻžāϰāĻŦāĻžāϰāĻāĻ•āĻŦāĻžāϰ
delayāύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ msāύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ msāϕ⧋āύ⧋ delay āύ⧇āχ
āϕ⧋āĻĨāĻžāϝāĻŧ āϚāϞ⧇Browser + Node.jsBrowser + Node.jsāĻļ⧁āϧ⧁ Node.js
Queuemacrotaskmacrotaskcheck phase

âąī¸ When would you use setImmediate over setTimeout(fn, 0)?​

setTimeout(fn, 0) āĻŽāĻžāύ⧇ āĻāχ āύāϝāĻŧ āϝ⧇ āĻ•āĻžāϜāϟāĻŋ āĻ āĻŋāĻ• 0ms āĻĒāϰ⧇ āĻšāĻŦ⧇ — minimum delay āϏāĻžāϧāĻžāϰāĻŖāϤ 1ms āĻŦāĻž āϤāĻžāϰ āĻŦ⧇āĻļāĻŋ āĻšāϝāĻŧāĨ¤ āĻāĻ›āĻžāĻĄāĻŧāĻž setTimeout-āĻāϰ execution timing, event loop-āĻāϰ āϕ⧋āύ phase-āĻ call āĻ•āϰāĻž āĻšāĻšā§āϛ⧇ āϤāĻžāϰ āωāĻĒāϰ āύāĻŋāĻ°ā§āĻ­āϰ āĻ•āϰ⧇āĨ¤

Node.js-āĻ setImmediate āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύ āϝāĻ–āύ:

  • āϕ⧋āύ⧋ I/O operation (file read, network request) āϏāĻŽā§āĻĒāĻ¨ā§āύ āĻšāĻ“āϝāĻŧāĻžāϰ āĻĒāϰ callback execute āĻ•āϰāϤ⧇ āϚāĻžāύāĨ¤
  • Consistent āĻāĻŦāĻ‚ predictable execution order āĻĻāϰāĻ•āĻžāϰāĨ¤
  • Timer overhead āĻ›āĻžāĻĄāĻŧāĻžāχ current operation āĻļ⧇āώ⧇ āĻ•āĻŋāϛ⧁ āĻ•āϰāϤ⧇ āϚāĻžāύāĨ¤
const fs = require("fs");

fs.readFile("file.txt", () => {
// āĻāχ I/O callback-āĻāϰ āϭ⧇āϤāϰ⧇:

setImmediate(() => {
console.log("1: setImmediate — āϏāĻŦāĻžāϰ āφāϗ⧇ āϚāϞāĻŦ⧇");
});

setTimeout(() => {
console.log("2: setTimeout — āĻĒāϰ⧇ āϚāϞāĻŦ⧇");
}, 0);
});

// Output āϏāĻŦāϏāĻŽāϝāĻŧ consistent:
// 1: setImmediate
// 2: setTimeout

âš ī¸ āϞāĻ•ā§āĻˇā§āϝ āĻ•āϰ⧁āύ: I/O callback-āĻāϰ āĻŦāĻžāχāϰ⧇ (top-level code-āĻ) setTimeout(fn, 0) āĻāĻŦāĻ‚ setImmediate-āĻāϰ order āĻ…āύāĻŋāĻļā§āϚāĻŋāϤ — system performance-āĻāϰ āωāĻĒāϰ āύāĻŋāĻ°ā§āĻ­āϰ āĻ•āϰ⧇ āϝ⧇āϕ⧋āύ⧋āϟāĻŋ āφāϗ⧇ āϚāϞāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤


🔗 Related Questions
  • How do you cancel a setInterval and why is it important to do so?
  • What is queueMicrotask and how does it differ from setImmediate?

queueMicrotask() āĻāĻ•āϟāĻŋ function āϕ⧇ microtask queue-āĻ āϝ⧋āĻ— āĻ•āϰ⧇āĨ¤ Microtask queue āϏāĻŦāϏāĻŽāϝāĻŧ macrotask queue āĻ“ check phase-āĻāϰ āφāϗ⧇ execute āĻšāϝāĻŧ — āĻ…āĻ°ā§āĻĨāĻžā§Ž current synchronous code āĻļ⧇āώ āĻšāĻ“āϝāĻŧāĻžāϰ āϏāĻžāĻĨ⧇ āϏāĻžāĻĨ⧇āĨ¤

console.log("1: sync start");

setTimeout(() => console.log("4: setTimeout"), 0);

setImmediate(() => console.log("5: setImmediate"));

queueMicrotask(() => console.log("3: microtask"));

Promise.resolve().then(() => console.log("3: promise (also microtask)"));

console.log("2: sync end");

// Output:
// 1: sync start
// 2: sync end
// 3: microtask ← current task āĻļ⧇āώ⧇, āϏāĻžāĻĨ⧇ āϏāĻžāĻĨ⧇
// 3: promise
// 4: setTimeout ← āĻĒāϰ⧇āϰ event loop iteration-āĻ
// 5: setImmediate ← I/O phase-āĻāϰ āĻĒāϰ⧇

Event loop-āĻ execution order:

Synchronous Code
↓
Microtask Queue ← queueMicrotask(), Promise.then()
↓
Macrotask Queue ← setTimeout(), setInterval()
↓
Check Phase ← setImmediate() [Node.js only]

queueMicrotask āĻ•āĻ–āύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻŦ⧇āύ: āϝāĻ–āύ āϕ⧋āύ⧋ āĻ•āĻžāϜ current synchronous execution āĻļ⧇āώ āĻšāĻ“āϝāĻŧāĻžāϰ āĻĒāϰāĻĒāϰāχ āĻ•āϰāϤ⧇ āϚāĻžāύ, āĻ•āĻŋāĻ¨ā§āϤ⧁ āϏ⧇āϟāĻŋ āϕ⧋āύ⧋ Promise-āĻāϰ āϏāĻžāĻĨ⧇ āϝ⧁āĻ•ā§āϤ āύāϝāĻŧāĨ¤ āϝ⧇āĻŽāύ — internal state update āĻ•āϰāĻžāϰ āĻĒāϰ UI re-render trigger āĻ•āϰāĻžāϰ āφāϗ⧇ āϕ⧋āύ⧋ cleanup logic āϚāĻžāϞāĻžāύ⧋āĨ¤


📌 25. How do you run async operations in parallel vs sequentially?​

🔗 Related Questions
  • Difference between await in a loop vs Promise.all
  • What is the difference between Promise.all and Promise.allSettled?
  • What is Promise.race and when is it useful?
  • How do you limit concurrency when running many async operations in parallel (e.g., p-limit)?

📌 26. What is the async module, and when is it useful?​

async āĻšāϞ⧋ āĻāĻ•āϟāĻŋ popular third-party Node.js library āϝāĻž complex asynchronous control flow — āϝ⧇āĻŽāύ series, parallel, waterfall, queue — āϏāĻšāĻœā§‡ manage āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ utility function āϏāϰāĻŦāϰāĻžāĻš āĻ•āϰ⧇āĨ¤

Native Promise āĻŦāĻž async/await āφāϏāĻžāϰ āφāϗ⧇ callback-based asynchronous code manage āĻ•āϰāĻž āϖ⧁āĻŦ āĻ•āĻ āĻŋāύ āĻ›āĻŋāϞāĨ¤ async module āϏ⧇āχ āϏāĻŽāĻ¸ā§āϝāĻž āϏāĻŽāĻžāϧāĻžāύ āĻ•āϰāϤ⧋āĨ¤

npm install async

āφāϜāϕ⧇āϰ āĻĻāĻŋāύ⧇ āĻ•āĻ–āύ useful:

  • Legacy codebase āϝ⧇āĻ–āĻžāύ⧇ callback pattern āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻšāĻšā§āϛ⧇āĨ¤
  • Concurrency limit āϏāĻš bulk operation āϚāĻžāϞāĻžāϤ⧇ āĻšāϞ⧇ (āϝ⧇āĻŽāύ āĻāĻ•āϏāĻžāĻĨ⧇ āϏāĻ°ā§āĻŦā§‹āĻšā§āϚ ā§ĢāϟāĻŋ request)āĨ¤
  • Complex dependency-based task flow manage āĻ•āϰāϤ⧇ āĻšāϞ⧇āĨ¤

🔗 Related Questions
  • How does async.waterfall compare to native Promise chaining?
  • What is async.parallel and async.series?

async.series — tasks āϗ⧁āϞ⧋ āĻāĻ•āϟāĻžāϰ āĻĒāϰ āĻāĻ•āϟāĻž āϚāĻžāϞāĻžāϝāĻŧāĨ¤ āĻāĻ•āϟāĻŋ āĻļ⧇āώ āύāĻž āĻšāϞ⧇ āĻĒāϰ⧇āϰāϟāĻŋ āĻļ⧁āϰ⧁ āĻšāϝāĻŧ āύāĻžāĨ¤ āĻāĻ•āϟāĻŋāϤ⧇ error āĻšāϞ⧇ āĻŦāĻžāĻ•āĻŋāϗ⧁āϞ⧋ āφāϰ āϚāϞ⧇ āύāĻžāĨ¤

const async = require("async");

async.series(
[
(callback) => {
setTimeout(() => {
console.log("Task 1 āĻļ⧇āώ");
callback(null, "result1");
}, 300);
},
(callback) => {
setTimeout(() => {
console.log("Task 2 āĻļ⧇āώ");
callback(null, "result2");
}, 100);
},
],
(err, results) => {
console.log(results); // ['result1', 'result2']
// āĻŽā§‹āϟ āϏāĻŽāϝāĻŧ: ~400ms
},
);

async.parallel — tasks āϗ⧁āϞ⧋ āĻāĻ•āϏāĻžāĻĨ⧇ āĻļ⧁āϰ⧁ āĻ•āϰ⧇āĨ¤ āϏāĻŦāϗ⧁āϞ⧋ complete āĻšāϞ⧇ final callback-āĻ āϏāĻŦ result āĻāĻ•āϏāĻžāĻĨ⧇ āĻĒāĻžāĻ“āϝāĻŧāĻž āϝāĻžāϝāĻŧāĨ¤

async.parallel(
[
(callback) => {
setTimeout(() => callback(null, "result1"), 300);
},
(callback) => {
setTimeout(() => callback(null, "result2"), 100);
},
],
(err, results) => {
console.log(results); // ['result1', 'result2']
// āĻŽā§‹āϟ āϏāĻŽāϝāĻŧ: ~300ms (āϏāĻŦāĻšā§‡āϝāĻŧ⧇ āĻŦ⧇āĻļāĻŋ āϏāĻŽāϝāĻŧ āύ⧇āĻ“āϝāĻŧāĻž task-āĻāϰ āϏāĻŽāĻžāύ)
},
);
async.seriesasync.parallel
ExecutionāĻāĻ•āϟāĻžāϰ āĻĒāϰ āĻāĻ•āϟāĻžāĻāĻ•āϏāĻžāĻĨ⧇
āĻŽā§‹āϟ āϏāĻŽāϝāĻŧāϏāĻŦ task-āĻāϰ āϏāĻŽāϝāĻŧ⧇āϰ āϝ⧋āĻ—āĻĢāϞāϏāĻŦāĻšā§‡āϝāĻŧ⧇ āϧ⧀āϰ task-āĻāϰ āϏāĻŽāϝāĻŧ
āĻ•āĻ–āύ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻ•āϟāĻŋāϰ output āφāϰ⧇āĻ•āϟāĻŋāϰ inputtasks āĻĒāϰāĻ¸ā§āĻĒāϰ independent

âš–ī¸ How does the async module compare to native Promise.all?​


📌 27. How do you handle parallel asynchronous operations in Node.js?​

Node.js-āĻ parallel async operation handle āĻ•āϰāĻžāϰ āϏāĻŦāĻšā§‡āϝāĻŧ⧇ āϏāĻšāϜ āĻāĻŦāĻ‚ modern āωāĻĒāĻžāϝāĻŧ āĻšāϞ⧋ Promise.all(), Promise.allSettled(), āĻŦāĻž Promise.race() āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāĨ¤


🔗 Related Questions
  • Difference between await in a loop vs Promise.all
  • What is the difference between Promise.all and Promise.allSettled?

Promise.all() — āϏāĻŦāϗ⧁āϞ⧋ Promise āϏāĻĢāϞāĻ­āĻžāĻŦ⧇ resolve āĻšāϞ⧇ āϤāĻŦ⧇āχ result āĻĻ⧇āϝāĻŧāĨ¤ āϝ⧇āϕ⧋āύ⧋ āĻāĻ•āϟāĻŋ reject āĻšāϞ⧇ āϏāĻžāĻĨ⧇ āϏāĻžāĻĨ⧇ āĻĒ⧁āϰ⧋ call āϟāĻŋ reject āĻšāϝāĻŧ⧇ āϝāĻžāϝāĻŧ āĻāĻŦāĻ‚ āĻŦāĻžāĻ•āĻŋāϗ⧁āϞ⧋āϰ result āĻĒāĻžāĻ“āϝāĻŧāĻž āϝāĻžāϝāĻŧ āύāĻžāĨ¤

const [user, posts, comments] = await Promise.all([
fetchUser(1),
fetchPosts(1),
fetchComments(1),
]);
// āϤāĻŋāύāϟāĻŋāϰ āϝ⧇āϕ⧋āύ⧋ āĻāĻ•āϟāĻŋ fail āĻ•āϰāϞ⧇ āϏāĻŦ āĻŦāĻžāϤāĻŋāϞ

Promise.allSettled() — āϏāĻŦāϗ⧁āϞ⧋ Promise complete āĻšāĻ“āϝāĻŧāĻž āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āĻ…āĻĒ⧇āĻ•ā§āώāĻž āĻ•āϰ⧇, āϕ⧇āω reject āĻšāϞ⧇āĻ“āĨ¤ āĻĒā§āϰāϤāĻŋāϟāĻŋāϰ āϜāĻ¨ā§āϝ āφāϞāĻžāĻĻāĻžāĻ­āĻžāĻŦ⧇ status: 'fulfilled' āĻŦāĻž status: 'rejected' āϜāĻžāύāĻž āϝāĻžāϝāĻŧāĨ¤

const results = await Promise.allSettled([
fetchUser(1),
fetchPosts(1),
fetchComments(1), // āĻāϟāĻŋ fail āĻ•āϰāϞ⧇āĻ“ āĻŦāĻžāĻ•āĻŋāϗ⧁āϞ⧋āϰ result āĻĒāĻžāĻŦā§‹
]);

results.forEach((result) => {
if (result.status === "fulfilled") {
console.log("āϏāĻĢāϞ:", result.value);
} else {
console.log("āĻŦā§āϝāĻ°ā§āĻĨ:", result.reason);
}
});
Promise.allPromise.allSettled
āĻāĻ•āϟāĻŋ fail āĻ•āϰāϞ⧇āϏāĻŦ āĻŦāĻžāϤāĻŋāϞāĻŦāĻžāĻ•āĻŋāϗ⧁āϞ⧋ āϚāϞāϤ⧇ āĻĨāĻžāϕ⧇
ResultāĻļ⧁āϧ⧁ values-āĻāϰ array{status, value/reason}-āĻāϰ array
āĻ•āĻ–āύ āĻŦā§āϝāĻŦāĻšāĻžāϰāϏāĻŦ result āĻĻāϰāĻ•āĻžāϰpartial failure acceptable

đŸŽī¸ What is Promise.race and when is it useful?​

Promise.race() — āĻĻ⧇āĻ“āϝāĻŧāĻž Promise āϗ⧁āϞ⧋āϰ āĻŽāĻ§ā§āϝ⧇ āϝ⧇āϟāĻŋ āϏāĻŦāĻžāϰ āφāϗ⧇ settle āĻšāϝāĻŧ (fulfilled āĻŦāĻž rejected āϝāĻžāχ āĻšā§‹āĻ•), āĻļ⧁āϧ⧁ āϏ⧇āϟāĻŋāϰ result return āĻ•āϰ⧇āĨ¤ āĻŦāĻžāĻ•āĻŋāϗ⧁āϞ⧋ āϤāĻ–āύāĻ“ background-āĻ āϚāϞāϤ⧇ āĻĒāĻžāϰ⧇, āĻ•āĻŋāĻ¨ā§āϤ⧁ āϤāĻžāĻĻ⧇āϰ result āφāϰ āĻĒāĻžāĻ“āϝāĻŧāĻž āϝāĻžāϝāĻŧ āύāĻžāĨ¤

const result = await Promise.race([
fetchFromServer1(), // ⧍ā§Ļā§Ļms āϞāĻžāĻ—āϞ⧋
fetchFromServer2(), // ā§Ģā§Ļā§Ļms āϞāĻžāĻ—āϞ⧋
fetchFromServer3(), // ā§§ā§Ļā§Ļms āϞāĻžāĻ—āϞ⧋ — āĻāϟāĻŋ āϜāĻŋāϤāĻŦ⧇
]);
// result = server3-āĻāϰ response

āĻ•āĻ–āύ useful:

Timeout implement āĻ•āϰāϤ⧇:

function withTimeout(promise, ms) {
const timeout = new Promise((_, reject) =>
setTimeout(() => reject(new Error("Timeout!")), ms),
);
return Promise.race([promise, timeout]);
}

// ā§Š āϏ⧇āϕ⧇āĻ¨ā§āĻĄā§‡āϰ āĻŽāĻ§ā§āϝ⧇ response āύāĻž āĻĒ⧇āϞ⧇ error
const data = await withTimeout(fetchData(), 3000);

Fastest available resource āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇:

// āĻāĻ•āĻžāϧāĻŋāĻ• CDN-āĻāϰ āĻŽāĻ§ā§āϝ⧇ āϝ⧇āϟāĻŋ āφāϗ⧇ respond āĻ•āϰ⧇
const asset = await Promise.race([
fetch("https://cdn1.example.com/file.js"),
fetch("https://cdn2.example.com/file.js"),
]);

đŸšĻ How do you limit concurrency when running many async operations in parallel?​

Promise.all() āĻĻāĻŋāϝāĻŧ⧇ āĻšāĻžāϜāĻžāϰ⧋ request āĻāĻ•āϏāĻžāĻĨ⧇ āĻĒāĻžāĻ āĻžāϞ⧇ server āĻŦāĻž rate limit āϏāĻŽāĻ¸ā§āϝāĻž āĻšāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤ āĻāχ āϏāĻŽāĻ¸ā§āϝāĻž āϏāĻŽāĻžāϧāĻžāύ⧇ concurrency limit āĻ•āϰāϤ⧇ āĻšāϝāĻŧāĨ¤

p-limit library āĻĻāĻŋāϝāĻŧ⧇ (recommended):

import pLimit from "p-limit";

const limit = pLimit(3); // āĻāĻ•āϏāĻžāĻĨ⧇ āϏāĻ°ā§āĻŦā§‹āĻšā§āϚ ā§ŠāϟāĻŋ

const urls = Array.from(
{ length: 20 },
(_, i) => `https://api.example.com/item/${i}`,
);

const results = await Promise.all(
urls.map((url) => limit(() => fetch(url).then((r) => r.json()))),
);
// ⧍ā§ĻāϟāĻŋ request āϚāϞāĻŦ⧇, āĻ•āĻŋāĻ¨ā§āϤ⧁ āϝ⧇āϕ⧋āύ⧋ āĻŽā§āĻšā§‚āĻ°ā§āϤ⧇ āϏāĻ°ā§āĻŦā§‹āĻšā§āϚ ā§ŠāϟāĻŋ active āĻĨāĻžāĻ•āĻŦ⧇

Manual chunking āĻĻāĻŋāϝāĻŧ⧇ (library āĻ›āĻžāĻĄāĻŧāĻž):

async function runInBatches(items, batchSize, asyncFn) {
const results = [];

for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize);
const batchResults = await Promise.all(batch.map(asyncFn));
results.push(...batchResults);
}

return results;
}

// āĻĒā§āϰāϤāĻŋ batch-āĻ ā§ĢāϟāĻŋ āĻ•āϰ⧇ process āĻšāĻŦ⧇
const data = await runInBatches(urls, 5, (url) =>
fetch(url).then((r) => r.json()),
);

âš ī¸ āϏāϤāĻ°ā§āĻ•āϤāĻž: Manual chunking-āĻ āĻāĻ•āϟāĻŋ batch-āĻāϰ āϏāĻŦāĻšā§‡āϝāĻŧ⧇ āϧ⧀āϰ task āϏāĻŽā§āĻĒāĻ¨ā§āύ āύāĻž āĻšāĻ“āϝāĻŧāĻž āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āĻĒāϰ⧇āϰ batch āĻļ⧁āϰ⧁ āĻšāϝāĻŧ āύāĻžāĨ¤ p-limit āĻāχ āϏāĻŽāĻ¸ā§āϝāĻž āĻāĻĄāĻŧāĻŋāϝāĻŧ⧇ āϚāϞ⧇ — āĻāĻ•āϟāĻŋ task āĻļ⧇āώ āĻšāĻ“āϝāĻŧāĻžāϰ āϏāĻžāĻĨ⧇ āϏāĻžāĻĨ⧇ āύāϤ⧁āύ āĻāĻ•āϟāĻŋ āĻļ⧁āϰ⧁ āĻ•āϰ⧇, āĻĢāϞ⧇ concurrency āϏāĻŦāϏāĻŽāϝāĻŧ āϏāĻ°ā§āĻŦā§‹āĻšā§āϚ āϏāĻ‚āĻ–ā§āϝāĻžāϝāĻŧ active āĻĨāĻžāϕ⧇āĨ¤


📌 28. What is an EventEmitter in Node.js?​

EventEmitter āĻšāϞ⧋ Node.js-āĻāϰ events module-āĻāϰ āĻāĻ•āϟāĻŋ core class āϝāĻž event-driven programming pattern implement āĻ•āϰ⧇āĨ¤ āĻāϟāĻŋ āĻĻāĻŋāϝāĻŧ⧇ custom event āϤ⧈āϰāĻŋ āĻ•āϰāĻž āϝāĻžāϝāĻŧ, āϏ⧇āχ event-āĻ listener (callback) register āĻ•āϰāĻž āϝāĻžāϝāĻŧ, āĻāĻŦāĻ‚ āĻĒāϰ⧇ event emit āĻ•āϰāϞ⧇ āϏāĻŦ listener āϗ⧁āϞ⧋ automatically execute āĻšāϝāĻŧāĨ¤

const { EventEmitter } = require("events");

const emitter = new EventEmitter();

// 'data' event-āĻ listener register āĻ•āϰāĻž
emitter.on("data", (payload) => {
console.log("Data āĻĒāĻžāĻ“āϝāĻŧāĻž āϗ⧇āϛ⧇:", payload);
});

// 'data' event emit āĻ•āϰāĻž
emitter.emit("data", { id: 1, name: "Alice" });
// Output: Data āĻĒāĻžāĻ“āϝāĻŧāĻž āϗ⧇āϛ⧇: { id: 1, name: 'Alice' }

Real-world Node.js-āĻ EventEmitter āϏāĻ°ā§āĻŦāĻ¤ā§āϰ āĻŦā§āϝāĻŦāĻšā§ƒāϤ āĻšāϝāĻŧ — fs, http, stream, process āϏāĻŦāχ āĻāϰ āωāĻĒāϰ āĻ­āĻŋāĻ¤ā§āϤāĻŋ āĻ•āϰ⧇ āϤ⧈āϰāĻŋāĨ¤ āύāĻŋāĻœā§‡āϰ class-āĻāĻ“ extend āĻ•āϰ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝāĻžāϝāĻŧ:

const { EventEmitter } = require("events");

class FileProcessor extends EventEmitter {
process(file) {
// āĻ•āĻžāϜ āĻļ⧁āϰ⧁
this.emit("start", file);
// ... processing ...
this.emit("done", { file, status: "success" });
}
}

const processor = new FileProcessor();
processor.on("start", (f) => console.log(`āĻļ⧁āϰ⧁ āĻšāϝāĻŧ⧇āϛ⧇: ${f}`));
processor.on("done", (result) => console.log("āĻļ⧇āώ:", result));
processor.process("report.pdf");

🔁 What is the once method vs on on an EventEmitter?​

on(event, listener) — āĻāĻ•āϟāĻŋ event-āĻ listener permanently register āĻ•āϰ⧇āĨ¤ Event āϝāϤāĻŦāĻžāϰ emit āĻšāĻŦ⧇, listener āϤāϤāĻŦāĻžāϰ call āĻšāĻŦ⧇āĨ¤

emitter.on("message", (msg) => {
console.log("Message:", msg);
});

emitter.emit("message", "āĻĒā§āϰāĻĨāĻŽ"); // ✅ āϚāϞāĻŦ⧇
emitter.emit("message", "āĻĻā§āĻŦāĻŋāϤ⧀āϝāĻŧ"); // ✅ āϚāϞāĻŦ⧇
emitter.emit("message", "āϤ⧃āϤ⧀āϝāĻŧ"); // ✅ āϚāϞāĻŦ⧇

once(event, listener) — listener āϟāĻŋ āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ āĻāĻ•āĻŦāĻžāϰ execute āĻšāϝāĻŧāĨ¤ āĻĒā§āϰāĻĨāĻŽāĻŦāĻžāϰ event emit āĻšāĻ“āϝāĻŧāĻžāϰ āĻĒāϰ⧇ listener āϟāĻŋ automatically remove āĻšāϝāĻŧ⧇ āϝāĻžāϝāĻŧāĨ¤

emitter.once("connection", (socket) => {
console.log("āĻĒā§āϰāĻĨāĻŽ connection āĻĒāĻžāĻ“āϝāĻŧāĻž āϗ⧇āϛ⧇");
});

emitter.emit("connection", socket1); // ✅ āϚāϞāĻŦ⧇
emitter.emit("connection", socket2); // ❌ āφāϰ āϚāϞāĻŦ⧇ āύāĻž

āĻ•āĻ–āύ āϕ⧋āύāϟāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻŦ⧇āύ:

ononce
āĻ•āϤāĻŦāĻžāϰ āϚāϞ⧇āĻŦāĻžāϰāĻŦāĻžāϰāĻļ⧁āϧ⧁ āĻāĻ•āĻŦāĻžāϰ
āĻ•āĻ–āύ āĻŦā§āϝāĻŦāĻšāĻžāϰongoing events (data, message)one-time events (ready, connection)
Manual removeoff() āĻĻāĻŋāϝāĻŧ⧇ āĻ•āϰāϤ⧇ āĻšāϝāĻŧAutomatic

âš ī¸ What is a memory leak risk with EventEmitters?​

EventEmitter-āĻ default āĻšāĻŋāϏ⧇āĻŦ⧇ āĻāĻ•āϟāĻŋ event-āĻ āϏāĻ°ā§āĻŦā§‹āĻšā§āϚ 10āϟāĻŋ listener register āĻ•āϰāĻž āϝāĻžāϝāĻŧāĨ¤ āĻāϰ āĻŦ⧇āĻļāĻŋ āĻšāϞ⧇ Node.js warning āĻĻ⧇āϝāĻŧāĨ¤ āĻ•āĻŋāĻ¨ā§āϤ⧁ āφāϏāϞ āϏāĻŽāĻ¸ā§āϝāĻž āĻšāϞ⧋ — on() āĻĻāĻŋāϝāĻŧ⧇ listener add āĻ•āϰ⧇ āĻĒāϰ⧇ off() āĻĻāĻŋāϝāĻŧ⧇ remove āύāĻž āĻ•āϰāϞ⧇ āϏ⧇āχ listener āĻāĻŦāĻ‚ āĻāϰ āϏāĻžāĻĨ⧇ āϏāĻ‚āĻļā§āϞāĻŋāĻˇā§āϟ āϏāĻŦ object memory-āϤ⧇ āφāϟāϕ⧇ āĻĨāĻžāϕ⧇, Garbage Collector āϏ⧇āϗ⧁āϞ⧋ free āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇ āύāĻžāĨ¤

āϏāĻžāϧāĻžāϰāĻŖ memory leak-āĻāϰ āωāĻĻāĻžāĻšāϰāĻŖ:

class DataService extends EventEmitter {}
const service = new DataService();

function setupHandler() {
const cache = new Array(10000).fill("data"); // āĻŦāĻĄāĻŧ object

// āĻĒā§āϰāϤāĻŋāĻŦāĻžāϰ call āĻšāϞ⧇ āύāϤ⧁āύ listener add āĻšāĻšā§āϛ⧇, āĻ•āĻŋāĻ¨ā§āϤ⧁ āĻ•āĻ–āύ⧋ remove āĻšāĻšā§āϛ⧇ āύāĻž
service.on("update", () => {
console.log(cache.length); // cache āϟāĻŋ memory-āϤ⧇ āφāϟāϕ⧇ āĻĨāĻžāĻ•āϛ⧇
});
}

setInterval(setupHandler, 1000); // ❌ āĻĒā§āϰāϤāĻŋ āϏ⧇āϕ⧇āĻ¨ā§āĻĄā§‡ leak āĻŦāĻžāĻĄāĻŧāϛ⧇

āϏāĻŽāĻžāϧāĻžāύ ā§§ — listener āϏāĻ āĻŋāĻ•āĻ­āĻžāĻŦ⧇ remove āĻ•āϰāĻž:

function setupHandler() {
const cache = new Array(10000).fill("data");
const handler = () => console.log(cache.length);

service.on("update", handler);

// āĻ•āĻžāϜ āĻļ⧇āώ⧇ remove āĻ•āϰāϤ⧇ āĻšāĻŦ⧇
return () => service.off("update", handler); // cleanup function return
}

const cleanup = setupHandler();
// āĻĒāϰ⧇ āϝāĻ–āύ āĻĻāϰāĻ•āĻžāϰ:
cleanup(); // ✅ listener remove, memory free

āϏāĻŽāĻžāϧāĻžāύ ⧍ — once() āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž (āϝāĻ–āύ āĻāĻ•āĻŦāĻžāϰāχ āĻĻāϰāĻ•āĻžāϰ):

service.once("update", () => {
console.log("āĻāĻ•āĻŦāĻžāϰ āϚāϞāĻŦ⧇, āϤāĻžāϰāĻĒāϰ automatically remove");
}); // ✅ āϕ⧋āύ⧋ manual cleanup āĻĻāϰāĻ•āĻžāϰ āύ⧇āχ

āϏāĻŽāĻžāϧāĻžāύ ā§Š — limit āĻŦāĻžāĻĄāĻŧāĻžāύ⧋ (āϝāĻĻāĻŋ āϏāĻ¤ā§āϝāĻŋāχ āĻŦ⧇āĻļāĻŋ listener āĻĻāϰāĻ•āĻžāϰ):

service.setMaxListeners(20); // warning āĻŦāĻ¨ā§āϧ āĻ•āϰāĻž — āĻ•āĻŋāĻ¨ā§āϤ⧁ root cause āĻ āĻŋāĻ• āĻ•āϰāĻž āωāϚāĻŋāϤ

📌 29. How do you handle uncaught exceptions in asynchronous code?​

Synchronous error āϏāĻžāϧāĻžāϰāĻŖ try/catch āĻĻāĻŋāϝāĻŧ⧇ āϧāϰāĻž āϝāĻžāϝāĻŧāĨ¤ āĻ•āĻŋāĻ¨ā§āϤ⧁ asynchronous code-āĻ error handle āύāĻž āĻ•āϰāϞ⧇ āϏ⧇āϟāĻŋ "uncaught" āĻšāϝāĻŧ⧇ āĻĒāĻĄāĻŧ⧇āĨ¤

async/await-āĻ try/catch:

async function fetchData() {
try {
const data = await riskyOperation();
return data;
} catch (err) {
console.error("Async error handled:", err.message);
}
}

Unhandled Promise rejection handle āĻ•āϰāĻž:

// Modern Node.js-āĻ unhandled rejection process crash āĻ•āϰāĻžāϤ⧇ āĻĒāĻžāϰ⧇
process.on("unhandledRejection", (reason, promise) => {
console.error("Unhandled Rejection:", reason);
// Log āĻ•āϰ⧁āύ, āϤāĻžāϰāĻĒāϰ gracefully shutdown āĻ•āϰ⧁āύ
process.exit(1);
});

Synchronous uncaught exception handle āĻ•āϰāĻž:

process.on("uncaughtException", (err) => {
console.error("Uncaught Exception:", err.message);
// cleanup āĻ•āϰ⧁āύ, āϤāĻžāϰāĻĒāϰ āĻ…āĻŦāĻļā§āϝāχ exit āĻ•āϰ⧁āύ
process.exit(1);
});

Production-āĻ recommended pattern:

async function main() {
try {
await startServer();
await connectDatabase();
} catch (err) {
console.error("Startup failed:", err);
process.exit(1);
}
}

// Global safety net — āĻļ⧁āϧ⧁ last resort āĻšāĻŋāϏ⧇āĻŦ⧇
process.on("unhandledRejection", (reason) => {
console.error("Unhandled:", reason);
process.exit(1);
});

main();

đŸ›Ąī¸ What is the role of process.on('uncaughtException') and when should you use it?​

uncaughtException āϤāĻ–āύ fire āĻšāϝāĻŧ āϝāĻ–āύ āϕ⧋āύ⧋ synchronous error āϕ⧋āύ⧋ try/catch āĻĻāĻŋāϝāĻŧ⧇ āϧāϰāĻž āĻĒāĻĄāĻŧ⧇āύāĻŋ āĻāĻŦāĻ‚ āϏāϰāĻžāϏāϰāĻŋ event loop-āĻ āĻĒ⧌āρāϛ⧇ āϗ⧇āϛ⧇āĨ¤ āĻāϟāĻŋ āĻāĻ•āϟāĻŋ last resort safety net — āĻāĻ–āĻžāύ⧇ āĻĒ⧌āρāĻ›āĻžāύ⧋ āĻŽāĻžāύ⧇āχ program-āĻāϰ āϕ⧋āĻĨāĻžāĻ“ error handling-āĻ āĻĢāĻžāρāĻ• āφāϛ⧇āĨ¤

process.on("uncaughtException", (err, origin) => {
// origin āĻšāĻŦ⧇ 'uncaughtException' āĻ…āĻĨāĻŦāĻž 'unhandledRejection'
console.error("Fatal error:", err.message);
console.error("Origin:", origin);

// ✅ āĻļ⧁āϧ⧁ āĻāχ āĻĻ⧁āĻŸā§‹ āĻ•āĻžāϜ āĻ•āϰ⧁āύ:
// ā§§. Error log āĻ•āϰ⧁āύ (file āĻŦāĻž monitoring service-āĻ)
// ⧍. Gracefully exit āĻ•āϰ⧁āύ
process.exit(1);
});

āĻ•āĻ–āύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻŦ⧇āύ:

  • Production-āĻ last-resort logging āĻāϰ āϜāĻ¨ā§āϝāĨ¤
  • pm2 āĻŦāĻž systemd-āĻāϰ āĻŽāϤ⧋ process manager-āĻāϰ āϏāĻžāĻĨ⧇ — crash āĻšāϞ⧇ automatically restart āĻšāĻŦ⧇āĨ¤
  • āĻ•āĻ–āύ⧋āχ primary error handling āĻšāĻŋāϏ⧇āĻŦ⧇ āύāϝāĻŧāĨ¤

âš–ī¸ What is the difference between uncaughtException and unhandledRejection?​

āĻĻ⧁āĻŸā§‹ āĻĻ⧇āĻ–āϤ⧇ āĻāĻ•āχ āĻŽāύ⧇ āĻšāϞ⧇āĻ“ āĻāĻĻ⧇āϰ source āφāϞāĻžāĻĻāĻž:

uncaughtException — synchronous code-āĻ throw āĻšāĻ“āϝāĻŧāĻž error āϝāĻž āϕ⧋āύ⧋ try/catch āϧāϰ⧇āύāĻŋāĨ¤

process.on("uncaughtException", (err) => {
console.error("Sync error āϧāϰāĻž āĻĒāĻĄāĻŧ⧇āϛ⧇:", err.message);
process.exit(1);
});

// āĻāϟāĻŋ uncaughtException trigger āĻ•āϰāĻŦ⧇:
setTimeout(() => {
throw new Error("Synchronous throw!"); // ❌ āϕ⧋āύ⧋ try/catch āύ⧇āχ
}, 100);

unhandledRejection — āϕ⧋āύ⧋ Promise reject āĻšāϝāĻŧ⧇āϛ⧇ āĻ•āĻŋāĻ¨ā§āϤ⧁ .catch() āĻŦāĻž try/catch āĻĻāĻŋāϝāĻŧ⧇ handle āĻ•āϰāĻž āĻšāϝāĻŧāύāĻŋāĨ¤

process.on("unhandledRejection", (reason, promise) => {
console.error("Unhandled Promise Rejection:", reason);
process.exit(1);
});

// āĻāϟāĻŋ unhandledRejection trigger āĻ•āϰāĻŦ⧇:
async function fail() {
throw new Error("Promise rejected!");
}

fail(); // ❌ await āύ⧇āχ, .catch() āύ⧇āχ

āĻĻ⧁āĻŸā§‹āϰ āϤ⧁āϞāύāĻž:

uncaughtExceptionunhandledRejection
SourceSynchronous throwPromise rejection
Callback parameters(err, origin)(reason, promise)
Node.js default behaviorProcess crashNode.js 15+ āĻĨ⧇āϕ⧇ crash
Handle āĻ•āϰāĻžāϰ āωāĻĒāĻžāϝāĻŧtry/catch.catch() āĻŦāĻž try/catch in async

⛔ Why is it dangerous to continue running after an uncaughtException?​

uncaughtException āĻŽāĻžāύ⧇ application āĻāĻ•āϟāĻŋ āĻ…āϜāĻžāύāĻž, unexpected state-āĻ āφāϛ⧇āĨ¤ āĻāχ āĻ…āĻŦāĻ¸ā§āĻĨāĻžāϝāĻŧ āϚāĻžāϞāĻŋāϝāĻŧ⧇ āϗ⧇āϞ⧇:

// ❌ āĻ…āĻ¤ā§āϝāĻ¨ā§āϤ āĻŦāĻŋāĻĒāĻœā§āϜāύāĻ• pattern
process.on("uncaughtException", (err) => {
console.error("Error logged:", err);
// exit āύāĻž āĻ•āϰ⧇ āϚāĻžāϞāĻŋāϝāĻŧ⧇ āϝāĻžāĻšā§āĻ›āĻŋ — āĻāϟāĻŋ āĻ•āϰāĻŦ⧇āύ āύāĻž
});

let totalAmount = 0;

async function processPayment(amount) {
totalAmount += amount; // Step 1: āĻšāϝāĻŧ⧇āϛ⧇
await saveToDatabase(); // Step 2: āĻāĻ–āĻžāύ⧇ throw āĻšāϞ⧋
await sendConfirmationEmail(); // Step 3: āφāϰ āĻšāϞ⧋ āύāĻž
// āĻĢāϞ⧇: āϟāĻžāĻ•āĻž āĻ•āĻžāϟāĻž āϗ⧇āϛ⧇, āĻ•āĻŋāĻ¨ā§āϤ⧁ confirmation āϝāĻžāϝāĻŧāύāĻŋ
// totalAmount corrupted state-āĻ āφāϛ⧇
}

āϕ⧀ āϕ⧀ āϏāĻŽāĻ¸ā§āϝāĻž āĻšāϤ⧇ āĻĒāĻžāϰ⧇:

  • Corrupted state: Variable āĻŦāĻž data structure āĻ…āĻ°ā§āϧ⧇āĻ• update āĻšāϝāĻŧ⧇ āφāϟāϕ⧇ āφāϛ⧇āĨ¤
  • Resource leak: Database connection, file handle āĻ–ā§‹āϞāĻž āϰāϝāĻŧ⧇ āϗ⧇āϛ⧇āĨ¤
  • Security risk: Authentication āĻŦāĻž authorization logic skip āĻšāϝāĻŧ⧇ āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇āĨ¤
  • Silent wrong results: Program āϚāϞāϛ⧇ āĻ•āĻŋāĻ¨ā§āϤ⧁ āϭ⧁āϞ output āĻĻāĻŋāĻšā§āϛ⧇āĨ¤
// ✅ āϏāĻ āĻŋāĻ• pattern — crash āĻ•āϰ⧁āύ, process manager restart āĻ•āϰ⧁āĻ•
process.on("uncaughtException", (err) => {
logger.fatal({ err }, "Uncaught exception — shutting down");

// Graceful shutdown: āϚāϞāĻŽāĻžāύ request āĻļ⧇āώ āĻ•āϰ⧁āύ, āύāϤ⧁āύ āύ⧇āĻŦ⧇āύ āύāĻž
server.close(() => {
process.exit(1); // āϏāĻŦāϏāĻŽāϝāĻŧ exit āĻ•āϰāϤ⧇ āĻšāĻŦ⧇
});

// Graceful shutdown-āĻ āĻŦ⧇āĻļāĻŋ āϏāĻŽāϝāĻŧ āϞāĻžāĻ—āϞ⧇ force exit
setTimeout(() => process.exit(1), 5000).unref();
});

🆚 try/catch āĻŦāύāĻžāĻŽ .catch() — āϕ⧋āύāϟāĻŋ āĻ•āĻ–āύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻŦ⧇āύ?​

try/catch — async/await context-āĻ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻšāϝāĻŧāĨ¤ Synchronous āĻāĻŦāĻ‚ asynchronous āωāĻ­āϝāĻŧ error āϧāϰāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤

// ✅ async/await-āĻ try/catch
async function fetchUser(id) {
try {
const res = await fetch(`/api/users/${id}`);

if (!res.ok) {
throw new Error(`HTTP error: ${res.status}`);
}

return await res.json();
} catch (err) {
// Network error āĻāĻŦāĻ‚ HTTP error āĻĻ⧁āĻŸā§‹āχ āĻāĻ–āĻžāύ⧇ āφāϏāĻŦ⧇
console.error("fetchUser failed:", err.message);
throw err; // upstream-āĻ re-throw āĻ•āϰ⧁āύ āϝāĻĻāĻŋ āĻĻāϰāĻ•āĻžāϰ āĻšāϝāĻŧ
}
}

.catch() — Promise chain-āĻ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻšāϝāĻŧāĨ¤ Chain-āĻāϰ āϝ⧇āϕ⧋āύ⧋ āϜāĻžāϝāĻŧāĻ—āĻžāϝāĻŧ error āĻšāϞ⧇ āϏāϰāĻžāϏāϰāĻŋ .catch()-āĻ āϚāϞ⧇ āφāϏ⧇āĨ¤

// ✅ Promise chain-āĻ .catch()
fetch("/api/users/1")
.then((res) => res.json())
.then((user) => processUser(user))
.catch((err) => {
// āωāĻĒāϰ⧇āϰ āϝ⧇āϕ⧋āύ⧋ step-āĻāϰ error āĻāĻ–āĻžāύ⧇ āφāϏāĻŦ⧇
console.error("Pipeline failed:", err.message);
});

āϗ⧁āϰ⧁āĻ¤ā§āĻŦāĻĒā§‚āĻ°ā§āĻŖ āĻĒāĻžāĻ°ā§āĻĨāĻ•ā§āϝ:

// ❌ try/catch āĻĻāĻŋāϝāĻŧ⧇ non-awaited Promise āϧāϰāĻž āϝāĻžāϝāĻŧ āύāĻž
async function broken() {
try {
fetchData(); // await āύ⧇āχ — error āϧāϰāĻž āĻĒāĻĄāĻŧāĻŦ⧇ āύāĻž!
} catch (err) {
console.error("āĻāϟāĻŋ āĻ•āĻ–āύ⧋ āϚāϞāĻŦ⧇ āύāĻž");
}
}

// ✅ āϏāĻ āĻŋāĻ• — await āĻĨāĻžāĻ•āϞ⧇ try/catch āĻ•āĻžāϜ āĻ•āϰ⧇
async function fixed() {
try {
await fetchData(); // await āφāϛ⧇
} catch (err) {
console.error("Error:", err.message); // ✅ āϧāϰāĻž āĻĒāĻĄāĻŧāĻŦ⧇
}
}

đŸ’Ĩ What happens with unhandled rejections?​

Node.js 14 āĻāĻŦāĻ‚ āφāϗ⧇: Warning print āĻšāϤ⧋ āĻ•āĻŋāĻ¨ā§āϤ⧁ process āϚāϞāϤ⧇ āĻĨāĻžāĻ•āϤ⧋āĨ¤

Node.js 15 āĻāĻŦāĻ‚ āĻĒāϰ⧇: Unhandled rejection āϏāϰāĻžāϏāϰāĻŋ process crash āĻ•āϰ⧇ — āĻ āĻŋāĻ• uncaughtException-āĻāϰ āĻŽāϤ⧋āĨ¤

// āĻāχ code Node.js 15+-āĻ process crash āĻ•āϰāĻŦ⧇:
async function fail() {
throw new Error("Rejected!");
}

fail(); // .catch() āύ⧇āχ, await āύ⧇āχ
// UnhandledPromiseRejection: process exit code 1

āϕ⧀āĻ­āĻžāĻŦ⧇ prevent āĻ•āϰāĻŦ⧇āύ:

// ✅ Pattern 1: āϏāĻŦāϏāĻŽāϝāĻŧ await āĻ•āϰ⧁āύ
const result = await riskyOperation();

// ✅ Pattern 2: .catch() chain āĻ•āϰ⧁āύ
riskyOperation().catch((err) => logger.error(err));

// ✅ Pattern 3: Global handler (last resort)
process.on("unhandledRejection", (reason, promise) => {
console.error("Unhandled rejection at:", promise);
console.error("Reason:", reason);
process.exit(1);
});

🚨 How do you handle multiple async errors?​

Promise.all āĻĻāĻŋāϝāĻŧ⧇ — āĻāĻ•āϟāĻŋ fail āĻ•āϰāϞ⧇ āϏāĻŦ āĻŦāĻžāϤāĻŋāϞ:

async function fetchDashboardData(userId) {
try {
const [user, posts, notifications] = await Promise.all([
fetchUser(userId),
fetchPosts(userId),
fetchNotifications(userId),
]);

return { user, posts, notifications };
} catch (err) {
// āϝ⧇āϕ⧋āύ⧋ āĻāĻ•āϟāĻŋ fail āĻ•āϰāϞ⧇ āĻāĻ–āĻžāύ⧇ āφāϏāĻŦ⧇
// āĻ•āĻŋāĻ¨ā§āϤ⧁ āϕ⧋āύāϟāĻŋ fail āĻ•āϰ⧇āϛ⧇ āϜāĻžāύāĻž āϝāĻžāĻŦ⧇ āύāĻž āϏāĻšāĻœā§‡
console.error("Dashboard load failed:", err.message);
throw err;
}
}

Promise.allSettled āĻĻāĻŋāϝāĻŧ⧇ — partial failure āϏāĻžāĻŽāϞāĻžāύ⧋:

async function fetchDashboardData(userId) {
const results = await Promise.allSettled([
fetchUser(userId),
fetchPosts(userId),
fetchNotifications(userId),
]);

// āĻĒā§āϰāϤāĻŋāϟāĻŋāϰ result āφāϞāĻžāĻĻāĻžāĻ­āĻžāĻŦ⧇ check āĻ•āϰāĻž āϝāĻžāĻšā§āϛ⧇
const [userResult, postsResult, notifResult] = results;

if (userResult.status === "rejected") {
// User āĻ›āĻžāĻĄāĻŧāĻž dashboard āĻĻ⧇āĻ–āĻžāύ⧋ āϏāĻŽā§āĻ­āĻŦ āύāϝāĻŧ
throw new Error("Critical: user fetch failed");
}

return {
user: userResult.value,
posts: postsResult.status === "fulfilled" ? postsResult.value : [], // Posts āύāĻž āĻĒ⧇āϞ⧇ empty array fallback
notifications: notifResult.status === "fulfilled" ? notifResult.value : [],
warnings: results
.filter((r) => r.status === "rejected")
.map((r) => r.reason.message),
};
}

Centralized error handler pattern — āĻŦāĻĄāĻŧ application-āĻāϰ āϜāĻ¨ā§āϝ:

// errors/AppError.js
class AppError extends Error {
constructor(message, statusCode, isOperational = true) {
super(message);
this.statusCode = statusCode;
this.isOperational = isOperational; // Expected error āĻ•āĻŋāύāĻž
}
}

// middleware/errorHandler.js
function globalErrorHandler(err, req, res, next) {
if (err instanceof AppError && err.isOperational) {
// Expected error — client-āϕ⧇ āϜāĻžāύāĻžāύ⧋ āϝāĻžāϝāĻŧ
return res.status(err.statusCode).json({
status: "error",
message: err.message,
});
}

// Unexpected error — log āĻ•āϰ⧁āύ, generic response āĻĻāĻŋāύ
logger.fatal({ err }, "Unexpected error");
res.status(500).json({ status: "error", message: "Internal server error" });
}

// Route-āĻ āĻŦā§āϝāĻŦāĻšāĻžāϰ:
async function getUser(req, res, next) {
try {
const user = await UserService.findById(req.params.id);
if (!user) throw new AppError("User not found", 404);
res.json(user);
} catch (err) {
next(err); // Central handler-āĻ āĻĒāĻžāĻ āĻžāύ⧋
}
}

📌 30. What are async hooks in Node.js?​

async_hooks āĻšāϞ⧋ Node.js-āĻāϰ āĻāĻ•āϟāĻŋ built-in module āϝāĻž asynchronous operation-āĻāϰ lifecycle track āĻ•āϰāϤ⧇ āĻĻ⧇āϝāĻŧāĨ¤ āĻĒā§āϰāϤāĻŋāϟāĻŋ async operation (Promise, setTimeout, fs.readFile āχāĻ¤ā§āϝāĻžāĻĻāĻŋ) āϤ⧈āϰāĻŋ āĻšāĻ“āϝāĻŧāĻž āĻĨ⧇āϕ⧇ āĻļ⧇āώ āĻšāĻ“āϝāĻŧāĻž āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āĻĒā§āϰāϤāĻŋāϟāĻŋ āϧāĻžāĻĒ⧇ callback execute āĻ•āϰāĻž āϝāĻžāϝāĻŧāĨ¤

āĻĒā§āϰāϤāĻŋāϟāĻŋ async resource-āĻāϰ āĻāĻ•āϟāĻŋ unique asyncId āĻāĻŦāĻ‚ āĻāĻ•āϟāĻŋ triggerAsyncId āĻĨāĻžāϕ⧇ (āϝ⧇ resource āĻāϟāĻŋ āϤ⧈āϰāĻŋ āĻ•āϰ⧇āϛ⧇ āϤāĻžāϰ id)āĨ¤ āĻāχ āĻĻ⧁āĻŸā§‹ āĻĻāĻŋāϝāĻŧ⧇ async operation-āĻāϰ āĻĒ⧁āϰ⧋ chain trace āĻ•āϰāĻž āϏāĻŽā§āĻ­āĻŦāĨ¤

const async_hooks = require("async_hooks");
const fs = require("fs");

const hook = async_hooks.createHook({
init(asyncId, type, triggerAsyncId) {
fs.writeSync(1, `Init: ${type} (asyncId: ${asyncId})\n`);
},
before(asyncId) {
fs.writeSync(1, `Before: ${asyncId}\n`);
},
after(asyncId) {
fs.writeSync(1, `After: ${asyncId}\n`);
},
destroy(asyncId) {
fs.writeSync(1, `Destroy: ${asyncId}\n`);
},
});

hook.enable();

setTimeout(() => {
fs.writeSync(1, "Timeout callback āϚāϞāϛ⧇\n");
}, 100);

âš ī¸ āϏāϤāĻ°ā§āĻ•āϤāĻž: async_hooks āĻāϰ performance overhead āωāĻ˛ā§āϞ⧇āĻ–āϝ⧋āĻ—ā§āϝāĨ¤ Production-āĻ āϏāϰāĻžāϏāϰāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āύāĻž āĻ•āϰ⧇ AsyncLocalStorage-āĻāϰ āĻŽāϤ⧋ higher-level API āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āωāϚāĻŋāϤāĨ¤

āĻ•āĻ–āύ useful:

  • Request tracing āĻāĻŦāĻ‚ distributed logging-āĻāĨ¤
  • APM (Application Performance Monitoring) tool āϤ⧈āϰāĻŋāϤ⧇āĨ¤
  • Async context propagation implement āĻ•āϰāϤ⧇āĨ¤

đŸ“Ļ What is AsyncLocalStorage and how does it replace async hooks for context propagation?​

AsyncLocalStorage āĻšāϞ⧋ async_hooks-āĻāϰ āωāĻĒāϰ āĻ­āĻŋāĻ¤ā§āϤāĻŋ āĻ•āϰ⧇ āϤ⧈āϰāĻŋ āĻāĻ•āϟāĻŋ high-level API āϝāĻž async operation-āĻāϰ āĻĒ⧁āϰ⧋ chain āϜ⧁āĻĄāĻŧ⧇ context (data) automatically carry āĻ•āϰ⧇ — āϕ⧋āύ⧋ function-āĻ manually parameter pass āύāĻž āĻ•āϰ⧇āχāĨ¤

āϏāĻŽāĻ¸ā§āϝāĻžāϟāĻž āĻŦā§‹āĻāĻž āϝāĻžāĻ• — āĻāĻ•āϟāĻŋ HTTP request āφāϏāϞ⧇ āĻ…āύ⧇āĻ• async step-āĻāϰ āĻŽāĻ§ā§āϝ āĻĻāĻŋāϝāĻŧ⧇ āϝāĻžāϝāĻŧāĨ¤ āĻĒā§āϰāϤāĻŋāϟāĻŋ step-āĻ requestId āĻŦāĻž userId āϜāĻžāύāϤ⧇ āĻšāϞ⧇ āϏāĻžāϧāĻžāϰāĻŖāϤ āϏāĻŦ function-āĻ parameter āĻšāĻŋāϏ⧇āĻŦ⧇ pass āĻ•āϰāϤ⧇ āĻšāϤ⧋:

// ❌ āĻ›āĻžāĻĄāĻŧāĻž AsyncLocalStorage — āϏāĻŦ āϜāĻžāϝāĻŧāĻ—āĻžāϝāĻŧ manually pass āĻ•āϰāϤ⧇ āĻšāĻšā§āϛ⧇
async function handleRequest(requestId) {
const user = await getUser(requestId); // pass āĻ•āϰāϤ⧇ āĻšāĻšā§āϛ⧇
const data = await fetchData(requestId); // āĻāĻ–āĻžāύ⧇āĻ“
await saveLog(requestId, user, data); // āĻāĻ–āĻžāύ⧇āĻ“
}

AsyncLocalStorage āĻĻāĻŋāϝāĻŧ⧇ āϏāĻŽāĻžāϧāĻžāύ:

const { AsyncLocalStorage } = require("async_hooks");

const storage = new AsyncLocalStorage();

// Middleware — request āφāϏāϞ⧇ context set āĻ•āϰāĻž āĻšāĻšā§āϛ⧇
function requestMiddleware(req, res, next) {
const context = {
requestId: crypto.randomUUID(),
userId: req.headers["x-user-id"],
startTime: Date.now(),
};

// āĻāχ context āϟāĻŋ āĻāχ request-āĻāϰ āϏāĻŦ async chain-āĻ automatically āĻĒāĻžāĻ“āϝāĻŧāĻž āϝāĻžāĻŦ⧇
storage.run(context, () => next());
}

// āϝ⧇āϕ⧋āύ⧋ nested async function-āĻ, parameter āĻ›āĻžāĻĄāĻŧāĻžāχ context āĻĒāĻžāĻ“āϝāĻŧāĻž āϝāĻžāĻšā§āϛ⧇
async function getUser() {
const { userId, requestId } = storage.getStore(); // ✅ parameter āĻ›āĻžāĻĄāĻŧāĻžāχ āĻĒāĻžāĻšā§āĻ›āĻŋ
console.log(`Request ${requestId}: user ${userId} fetch āĻ•āϰāĻž āĻšāĻšā§āϛ⧇`);
return db.query("SELECT * FROM users WHERE id = ?", [userId]);
}

async function saveLog(data) {
const { requestId, startTime } = storage.getStore(); // ✅ āĻāĻ–āĻžāύ⧇āĻ“
const duration = Date.now() - startTime;
await logger.log({ requestId, duration, data });
}

async function handleRequest(req, res) {
const user = await getUser(); // requestId pass āĻ•āϰāϤ⧇ āĻšāĻšā§āϛ⧇ āύāĻž
await saveLog(user); // āĻāĻ–āĻžāύ⧇āĻ“ āύāĻž
res.json(user);
}

āĻĻ⧁āϟāĻŋ request āĻāĻ•āϏāĻžāĻĨ⧇ āφāϏāϞ⧇āĻ“ context āφāϞāĻžāĻĻāĻž āĻĨāĻžāϕ⧇:

// Request A āĻāĻŦāĻ‚ Request B āĻāĻ•āχ āϏāĻŽāϝāĻŧ⧇ āϚāϞāϞ⧇āĻ“
// āĻĒā§āϰāϤāĻŋāϟāĻŋāϰ storage.getStore() āύāĻŋāĻœā§‡āϰ context āĻĻ⧇āĻ–āĻžāĻŦ⧇ — āϕ⧋āύ⧋ mixing āĻšāĻŦ⧇ āύāĻž
storage.run({ requestId: "A" }, () => handleRequest());
storage.run({ requestId: "B" }, () => handleRequest());
async_hooksAsyncLocalStorage
LevelLow-levelHigh-level
PerformanceāĻŦ⧇āĻļāĻŋ overheadāĻ…āύ⧇āĻ• āĻ•āĻŽ overhead
āĻŦā§āϝāĻŦāĻšāĻžāϰ⧇āϰ āϏāĻšāϜāϤāĻžāϜāϟāĻŋāϞāϏāĻšāϜ
Context propagationManualAutomatic

📌 31. What is the util.promisify function and how does it work?​

util.promisify āĻšāϞ⧋ Node.js-āĻāϰ built-in āĻāĻ•āϟāĻŋ utility function āϝāĻž Node.js-āĻāϰ standard callback(err, result) pattern āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰāĻž āϝ⧇āϕ⧋āύ⧋ function āϕ⧇ automatically Promise-based function-āĻ convert āĻ•āϰ⧇āĨ¤

const util = require("util");
const fs = require("fs");

// fs.readFile āĻāĻ•āϟāĻŋ callback-based function
// āĻ¸ā§āĻŦāĻžāĻ­āĻžāĻŦāĻŋāĻ• āĻŦā§āϝāĻŦāĻšāĻžāϰ:
fs.readFile("file.txt", "utf8", (err, data) => {
if (err) throw err;
console.log(data);
});

// util.promisify āĻĻāĻŋāϝāĻŧ⧇ Promise-āĻ convert:
const readFile = util.promisify(fs.readFile);

// āĻāĻ–āύ async/await āĻĻāĻŋāϝāĻŧ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝāĻžāĻšā§āϛ⧇
const data = await readFile("file.txt", "utf8"); // ✅ āĻ…āύ⧇āĻ• āĻĒāϰāĻŋāĻˇā§āĻ•āĻžāϰ
console.log(data);

util.promisify āϭ⧇āϤāϰ⧇ āϕ⧀āĻ­āĻžāĻŦ⧇ āĻ•āĻžāϜ āĻ•āϰ⧇:

// util.promisify āĻŽā§‚āϞāϤ āĻāϟāĻžāχ āĻ•āϰ⧇:
function promisify(fn) {
return function (...args) {
return new Promise((resolve, reject) => {
fn(...args, (err, result) => {
if (err) reject(err);
else resolve(result);
});
});
};
}

đŸ› ī¸ How do you manually wrap a callback function in a Promise?​

āϝāĻ–āύ function āϟāĻŋ util.promisify-āĻāϰ standard pattern āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰ⧇ āύāĻž, āϤāĻ–āύ manually new Promise() āĻĻāĻŋāϝāĻŧ⧇ wrap āĻ•āϰāϤ⧇ āĻšāϝāĻŧāĨ¤

// āĻāĻ•āϟāĻŋ third-party callback-based function
function connectToDatabase(host, port, callback) {
// ... connection logic ...
if (success) callback(null, connection);
else callback(new Error("Connection failed"));
}

// Manual Promise wrapper:
function connectToDatabaseAsync(host, port) {
return new Promise((resolve, reject) => {
connectToDatabase(host, port, (err, connection) => {
if (err) {
reject(err); // error āĻšāϞ⧇ Promise reject
} else {
resolve(connection); // āϏāĻĢāϞ āĻšāϞ⧇ Promise resolve
}
});
});
}

// āĻāĻ–āύ async/await āĻĻāĻŋāϝāĻŧ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ:
try {
const connection = await connectToDatabaseAsync("localhost", 5432);
console.log("Connected:", connection);
} catch (err) {
console.error("Failed:", err.message);
}

🧩 How do you handle callbacks that call callback(result) instead of callback(err, result)?​

āĻ•āĻŋāϛ⧁ library (āĻŦāĻŋāĻļ⧇āώāϤ āĻĒ⧁āϰāύ⧋) error-first pattern āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰ⧇ āύāĻž — āϤāĻžāϰāĻž āϏāϰāĻžāϏāϰāĻŋ callback(result) call āĻ•āϰ⧇āĨ¤ āĻāĻ•ā§āώ⧇āĻ¤ā§āϰ⧇ util.promisify āĻ•āĻžāϜ āĻ•āϰāĻŦ⧇ āύāĻž, manually wrap āĻ•āϰāϤ⧇ āĻšāĻŦ⧇āĨ¤

// ❌ Non-standard pattern — error parameter āύ⧇āχ
function getUserById(id, callback) {
const user = database.find(id);
callback(user); // āĻļ⧁āϧ⧁ result, āϕ⧋āύ⧋ err āύ⧇āχ
}

// ✅ Manual wrapper āĻĻāĻŋāϝāĻŧ⧇ handle āĻ•āϰāĻž:
function getUserByIdAsync(id) {
return new Promise((resolve, reject) => {
getUserById(id, (user) => {
if (!user) {
reject(new Error(`User ${id} āĻĒāĻžāĻ“āϝāĻŧāĻž āϝāĻžāϝāĻŧāύāĻŋ`));
} else {
resolve(user);
}
});
});
}

āϝāĻĻāĻŋ success āĻāĻŦāĻ‚ error āĻĻ⧁āĻŸā§‹ āφāϞāĻžāĻĻāĻž callback āĻĨāĻžāϕ⧇:

// āĻ•āĻŋāϛ⧁ library āĻāχ pattern āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇
function loadImage(url, onSuccess, onError) {
// ... loading logic ...
}

// Promise wrapper:
function loadImageAsync(url) {
return new Promise((resolve, reject) => {
loadImage(url, resolve, reject); // resolve āĻāĻŦāĻ‚ reject āϏāϰāĻžāϏāϰāĻŋ pass
});
}

const image = await loadImageAsync("https://example.com/photo.jpg");

util.promisify-āϕ⧇ custom symbol āĻĻāĻŋāϝāĻŧ⧇ override āĻ•āϰāĻž:

āϕ⧋āύ⧋ function-āĻāϰ āύāĻŋāϜāĻ¸ā§āĻŦ promisified version āĻĨāĻžāĻ•āϞ⧇ util.promisify.custom symbol āĻĻāĻŋāϝāĻŧ⧇ define āĻ•āϰāĻž āϝāĻžāϝāĻŧ:

function getUserById(id, callback) {
callback(database.find(id)); // non-standard
}

// Custom promisified version define āĻ•āϰāĻž
getUserById[util.promisify.custom] = (id) => {
return new Promise((resolve, reject) => {
const user = database.find(id);
user ? resolve(user) : reject(new Error("Not found"));
});
};

const getUserByIdAsync = util.promisify(getUserById);
// āĻāĻ–āύ util.promisify custom version āϟāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻŦ⧇ ✅
const user = await getUserByIdAsync(42);