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 āĻŦāϞāĻž āĻšāϝāĻŧāĨ¤
Code ExampleJavaScriptClick to view details
// 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āĨ¤
Code ExampleJavaScriptClick to view details
// 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-āĻāϰ āĻŽāϤ⧠āĻĻā§āĻāϤ⧠āĻāĻŦāĻ āĻĒāĻĄāĻŧāϤ⧠āϏāĻžāĻšāĻžāϝā§āϝ āĻāϰā§āĨ¤
Code ExampleJavaScriptClick to view details
// 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āĨ¤
Code ExampleJavaScriptClick to view details
// 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?â
āϝāĻāύ āĻāĻāĻāĻŋ callback āĻ āύā§āϝ āĻāĻāĻāĻŋ function āĻŦāĻž library-āĻā§ pass āĻāϰāĻž āĻšāϝāĻŧ, āϤāĻāύ āĻāĻĒāύāĻžāϰ code-āĻāϰ execution-āĻāϰ āύāĻŋāϝāĻŧāύā§āϤā§āϰāĻŖ āĻāĻĒāύāĻžāϰ āĻšāĻžāϤ āĻĨā§āĻā§ āĻŦā§āϰāĻŋāϝāĻŧā§ āϏ⧠āĻ third-party function-āĻāϰ āĻšāĻžāϤ⧠āĻāϞ⧠āϝāĻžāϝāĻŧ â āĻāĻā§āĻ āĻŦāϞ⧠Inversion of ControlāĨ¤ āĻāĻĒāύāĻŋ āύāĻŋāĻā§ callback-āĻāĻŋ call āĻāϰāĻā§āύ āύāĻž, āĻŦāϰāĻ āĻŦāĻŋāĻļā§āĻŦāĻžāϏ āĻāϰāĻā§āύ āϝ⧠āĻ āύā§āϝ function āϏā§āĻāĻŋ āϏāĻ āĻŋāĻāĻāĻžāĻŦā§ call āĻāϰāĻŦā§āĨ¤
āĻāĻ "āĻŦāĻŋāĻļā§āĻŦāĻžāϏ"-āĻāϰ āĻŽāϧā§āϝā§āĻ āϏāĻŽāϏā§āϝāĻž āϞā§āĻāĻŋāϝāĻŧā§ āĻĨāĻžāĻā§, āĻāĻžāϰāĻŖ āϏā§āĻ function āϝāĻĻāĻŋ buggy āĻŦāĻž malicious āĻšāϝāĻŧ, āϤāĻžāĻšāϞ⧠callback-āĻāĻŋ:
- āĻāĻāύ⧠call āύāĻž-āĻ āĻšāϤ⧠āĻĒāĻžāϰ⧠(silently ignored)āĨ¤
- āĻāĻāĻžāϧāĻŋāĻāĻŦāĻžāϰ call āĻšāϤ⧠āĻĒāĻžāϰ⧠(āĻāĻļāĻžāύā§āϰā§āĻĒ āĻāĻāĻŦāĻžāϰā§āϰ āĻŦāĻĻāϞā§)āĨ¤
- āĻā§āĻŦ āĻĻā§āϰā§āϤ (synchronously) āĻ āĻĨāĻŦāĻž āĻā§āĻŦ āĻĻā§āϰāĻŋāϤ⧠call āĻšāϤ⧠āĻĒāĻžāϰā§, āϝāĻž race condition āϤā§āϰāĻŋ āĻāϰāϤ⧠āĻĒāĻžāϰā§āĨ¤
- āĻā§āϞ argument āĻŦāĻž āĻā§āϞ
thiscontext āύāĻŋāϝāĻŧā§ call āĻšāϤ⧠āĻĒāĻžāϰā§āĨ¤
// â āĻā§āĻāĻāĻŋāĻĒā§āϰā§āĻŖ â thirdPartyLibrary-āĻāϰ āĻāĻĒāϰ āϏāĻŽā§āĻĒā§āϰā§āĻŖ āύāĻŋāϰā§āĻāϰāĻļā§āϞ
thirdPartyLibrary.process(data, function (err, result) {
chargeCustomerCard(); // āϝāĻĻāĻŋ callback āĻĻā§āĻāĻŦāĻžāϰ āĻāϞā§, customer-āĻāϰ card āĻĻā§āĻāĻŦāĻžāϰ charge āĻšāĻŦā§!
});
Promise āĻā§āĻāĻžāĻŦā§ āĻāĻ āϏāĻŽāϏā§āϝāĻž āĻāĻŽāĻžāϝāĻŧ:
Promise-āĻāϰ āĻā§āώā§āϤā§āϰ⧠control āĻĒā§āϰā§āĻĒā§āϰāĻŋ āĻ
āύā§āϝā§āϰ āĻšāĻžāϤ⧠āĻĨāĻžāĻā§ āύāĻž â Promise āύāĻŋāĻā§āĻ guarantee āĻĻā§āϝāĻŧ āϝ⧠āĻāĻāĻŋ āĻ āĻŋāĻ āĻāĻāĻŦāĻžāϰ resolve/reject āĻšāĻŦā§, state āĻāĻāĻŦāĻžāϰ fix āĻšāϝāĻŧā§ āĻā§āϞ⧠āĻāϰ āĻŦāĻĻāϞāĻžāĻŦā§ āύāĻž (immutability), āĻāĻŦāĻ handler āĻā§āϞ⧠āϏāĻŦāϏāĻŽāϝāĻŧ asynchronously call āĻšāĻŦā§ (āĻāĻāύ⧠synchronously āύāϝāĻŧ)āĨ¤ āĻāĻ āĻāĻžāϰāĻŖā§ Promise/async-await-āĻā§ callback-āĻāϰ āϤā§āϞāύāĻžāϝāĻŧ āĻŦā§āĻļāĻŋ predictable āĻāĻŦāĻ trustworthy āĻŽāύ⧠āĻāϰāĻž āĻšāϝāĻŧāĨ¤
đ 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-āĻ āϰā§āĻĒāĻžāύā§āϤāϰ āĻāϰā§āĨ¤
Code ExampleJavaScriptClick to view details
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 āĻāϰāĻž:
Code ExampleJavaScriptClick to view details
// āύāĻŋāĻā§āϰ āϤā§āϰāĻŋ 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 āĻā§āĻāĻžāĻŦā§ āϤā§āϰāĻŋ āĻāϰāϤ⧠āĻšāϝāĻŧ
Code ExampleJavaScriptClick to view details
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 āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āĻšāϝāĻŧ:
Code ExampleJavaScriptClick to view details
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);
}
});
});
- 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
Code ExampleJavaScriptClick to view details
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 āύāĻž āĻāϰāĻž
Code ExampleJavaScriptClick to view details
// â āĻā§āϞ â 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)
Code ExampleJavaScriptClick to view details
// â āĻā§āϞ â āĻāĻŦāĻžāϰ 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() āύāĻž āϰāĻžāĻāĻž
Code ExampleJavaScriptClick to view details
// â āĻā§āϞ â āĻļā§āϧ⧠āĻļā§āώ⧠āĻāĻāĻāĻŋ .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 āĻļā§āώ āĻāϰāĻž
Code ExampleJavaScriptClick to view details
// â āĻŦāĻŋāĻĒāĻā§āĻāύāĻ â 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 āĻāϰāĻž
Code ExampleJavaScriptClick to view details
// â āĻ
āĻĒā§āϰāϝāĻŧā§āĻāύā§āϝāĻŧ 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;
}
| āĻŦāĻŋāώāϝāĻŧ | āĻŽā§āϞ āĻāĻĨāĻž |
|---|---|
| Promise | Asynchronous operation-āĻāϰ future result represent āĻāϰ⧠|
| States | pending â fulfilled āĻ
āĻĨāĻŦāĻž rejected |
| Global Rejection | process.on('unhandledRejection') āĻĻāĻŋāϝāĻŧā§ handle āĻāϰāϤ⧠āĻšāϝāĻŧ |
| Chaining | āĻĒā§āϰāϤāĻŋāĻāĻŋ .then()-āĻ āĻ
āĻŦāĻļā§āϝāĻ return āĻāϰāϤ⧠āĻšāĻŦā§ |
| āϏāĻŦāĻā§āϝāĻŧā§ āĻŦāĻĄāĻŧ pitfall | return āύāĻž āĻāϰāĻž āĻāĻŦāĻ .catch() āύāĻž āϰāĻžāĻāĻž |
đ¨ How are errors propagated in Promise chains?â
- What is the difference between
Promise.resolve()andnew Promise(resolve => resolve())? - How do you handle Promise rejections globally?
āϝāĻĻāĻŋ āĻā§āύ⧠Promise reject āĻšāϝāĻŧ āĻāĻŦāĻ āϏā§āĻāĻžāύ⧠.catch() āύāĻž āĻĨāĻžāĻā§, āϏā§āĻāĻŋ unhandled rejection āĻšāϝāĻŧāĨ¤ Production-āĻ āĻāĻāĻŋ āĻā§āĻŦāĻ āĻŦāĻŋāĻĒāĻā§āĻāύāĻ āĻāĻžāϰāĻŖ error āύā§āϰāĻŦā§ āĻšāĻžāϰāĻŋāϝāĻŧā§ āϝāĻžāϝāĻŧāĨ¤
unhandledRejection Event
Code ExampleJavaScriptClick to view details
// 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
Code ExampleJavaScriptClick to view details
// 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 āĻāϰā§āĨ¤ āϤāĻžāĻ
unhandledRejectionhandler āϰāĻžāĻāĻž production-āĻ āĻ āĻĒāϰāĻŋāĻšāĻžāϰā§āϝāĨ¤
đ 23. What is async/await, and how does it simplify asynchronous code?â
async/await āĻšāϞ⧠JavaScript-āĻāϰ āĻāĻāĻāĻŋ syntax āϝāĻž Promise-based asynchronous code āĻā§ synchronous code-āĻāϰ āĻŽāϤ⧠āĻĻā§āĻāϤ⧠āĻ āĻĒāĻĄāĻŧāϤ⧠āϏāĻžāĻšāĻžāϝā§āϝ āĻāϰā§āĨ¤
asynckeyword āĻĻāĻŋāϝāĻŧā§ āĻāĻāĻāĻŋ function declare āĻāϰāϞ⧠āϏā§āĻāĻŋ āϏāĻŦāϏāĻŽāϝāĻŧ āĻāĻāĻāĻŋ Promise return āĻāϰā§āĨ¤awaitkeyword āĻļā§āϧā§āĻŽāĻžāϤā§āϰasyncfunction-āĻāϰ āĻā§āϤāϰ⧠āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āϝāĻžāϝāĻŧāĨ¤ āĻāĻāĻŋ āĻāĻāĻāĻŋ 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?â
await āĻļā§āϧā§āĻŽāĻžāϤā§āϰ āϏā§āĻ async function-āĻāĻŋāϰ execution pause āĻāϰ⧠āϝā§āĻāĻžāύ⧠āĻāĻāĻŋ āϞā§āĻāĻž āĻšāϝāĻŧā§āĻā§ â āĻĒā§āϰ⧠program āĻŦāĻž JavaScript-āĻāϰ main thread āĻā§ block āĻāϰ⧠āύāĻžāĨ¤ await-āĻ āĻĒā§āĻāĻāĻžāϞ⧠function-āĻāĻŋ āϏāĻžāĻĨā§ āϏāĻžāĻĨā§ control event loop-āĻā§ āĻĢāĻŋāϰāĻŋāϝāĻŧā§ āĻĻā§āϝāĻŧ, āĻĢāϞ⧠āĻŦāĻžāĻāĻŋ synchronous code (āĻāĻŦāĻ āĻ
āύā§āϝ āĻā§āύ⧠function) āĻāϞāϤ⧠āĻĨāĻžāĻāϤ⧠āĻĒāĻžāϰā§āĨ¤ Promise āĻāĻŋ resolve/reject āĻšāϞā§, JavaScript engine āϏā§āĻ async function-āĻāϰ execution āĻ āĻŋāĻ āϝā§āĻāĻžāύ⧠āĻĨā§āĻŽā§ āĻāĻŋāϞ āϏā§āĻāĻžāύ āĻĨā§āĻā§ āĻāĻŦāĻžāϰ āĻļā§āϰ⧠āĻāϰ⧠(āĻāĻāĻŋ āĻā§āϤāϰ⧠āĻā§āϤāϰ⧠Promise .then()-āĻāϰāĻ syntactic sugar)āĨ¤
Code ExampleJavaScriptClick to view details
console.log("1: āĻļā§āϰā§");
async function fetchData() {
console.log("2: fetch āĻļā§āϰ⧠āĻšāϞā§");
await new Promise((resolve) => setTimeout(resolve, 100)); // āĻāĻāĻžāύ⧠āĻļā§āϧ⧠fetchData() pause āĻšāϝāĻŧ
console.log("4: fetch āĻļā§āώ, resume āĻšāϞā§");
}
fetchData();
console.log("3: fetchData() call āĻāϰāĻžāϰ āĻĒāϰāĻĒāϰāĻ āĻāĻāĻŋ āĻāϞ⧠â main thread block āĻšāϝāĻŧāύāĻŋ!");
// Output:
// 1: āĻļā§āϰā§
// 2: fetch āĻļā§āϰ⧠āĻšāϞā§
// 3: fetchData() call āĻāϰāĻžāϰ āĻĒāϰāĻĒāϰāĻ āĻāĻāĻŋ āĻāϞ⧠â main thread block āĻšāϝāĻŧāύāĻŋ!
// 4: fetch āĻļā§āώ, resume āĻšāϞ⧠(~100ms āĻĒāϰā§)
- Is
async/awaitblocking or non-blocking? - How does it work under the hood (Promises)?
- How do you handle errors in
async/awaitusingtry/catch?
async/await-āĻ error handle āĻāϰāĻžāϰ āĻāύā§āϝ standard try/catch block āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āĻšāϝāĻŧāĨ¤ āϝāĻĻāĻŋ await āĻāϰāĻž āĻā§āύ⧠Promise reject āĻšāϝāĻŧ, āϤāĻžāĻšāϞ⧠āϏā§āĻāĻŋ automatically catch block-āĻ āĻāϞ⧠āϝāĻžāϝāĻŧāĨ¤
Code ExampleJavaScriptClick to view details
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() āĻĻāĻŋāϝāĻŧā§ āĻĨāĻžāĻŽāĻžāύ⧠āĻšāϝāĻŧāĨ¤
Code ExampleJavaScriptClick to view details
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-āĻāϰ āĻĒāϰāĻĒāϰāĻ āĻāϞāĻŦā§");
});
āϤāĻŋāύāĻāĻŋāϰ āϤā§āϞāύāĻž:
| āĻŦā§āĻļāĻŋāώā§āĻā§āϝ | setTimeout | setInterval | setImmediate |
|---|---|---|---|
| āĻāϤāĻŦāĻžāϰ āĻāϞ⧠| āĻāĻāĻŦāĻžāϰ | āĻŦāĻžāϰāĻŦāĻžāϰ | āĻāĻāĻŦāĻžāϰ |
| delay | āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ ms | āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ ms | āĻā§āύ⧠delay āύā§āĻ |
| āĻā§āĻĨāĻžāϝāĻŧ āĻāϞ⧠| Browser + Node.js | Browser + Node.js | āĻļā§āϧ⧠Node.js |
| Queue | macrotask | macrotask | check 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 āĻļā§āώ⧠āĻāĻŋāĻā§ āĻāϰāϤ⧠āĻāĻžāύāĨ¤
Code ExampleJavaScriptClick to view details
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-āĻāϰ āĻāĻĒāϰ āύāĻŋāϰā§āĻāϰ āĻāϰ⧠āϝā§āĻā§āύā§āĻāĻŋ āĻāĻā§ āĻāϞāϤ⧠āĻĒāĻžāϰā§āĨ¤
- How do you cancel a
setIntervaland why is it important to do so? - What is
queueMicrotaskand how does it differ fromsetImmediate?
queueMicrotask() āĻāĻāĻāĻŋ function āĻā§ microtask queue-āĻ āϝā§āĻ āĻāϰā§āĨ¤ Microtask queue āϏāĻŦāϏāĻŽāϝāĻŧ macrotask queue āĻ check phase-āĻāϰ āĻāĻā§ execute āĻšāϝāĻŧ â āĻ
āϰā§āĻĨāĻžā§ current synchronous code āĻļā§āώ āĻšāĻāϝāĻŧāĻžāϰ āϏāĻžāĻĨā§ āϏāĻžāĻĨā§āĨ¤
Code ExampleJavaScriptClick to view details
console.log("1: sync start");
setTimeout(() => console.log("setTimeout"), 0);
setImmediate(() => console.log("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
// āĻāϰāĻĒāϰ 'setTimeout' āĻāĻŦāĻ 'setImmediate' â āĻāĻ āĻĻā§āĻā§āϰ āĻŽāϧā§āϝ⧠āĻā§āύāĻāĻž āĻāĻā§ āĻāϞāĻŦā§
// āϤāĻž top-level code-āĻ āĻ
āύāĻŋāĻļā§āĻāĻŋāϤ (āĻāĻĒāϰ⧠āĻāϞā§āϞā§āĻāĻŋāϤ āĻāĻžāϰāĻŖā§āĻ); I/O callback-āĻāϰ
// āĻā§āϤāϰ āĻĨā§āĻā§ āĻāĻžāϞāĻžāϞ⧠setImmediate āϏāĻŦāϏāĻŽāϝāĻŧ setTimeout-āĻāϰ āĻāĻā§ āĻāϞāϤāĨ¤
Event loop-āĻ execution order:
Code ExampleClick to view details
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?â
āϏāĻāĻā§āώā§āĻĒā§ â dependency āĻāĻā§ āĻāĻŋāύāĻž āϏā§āĻāĻžāĻ āĻŽā§āϞ āĻŦāĻŋāĻŦā§āĻā§āϝ āĻŦāĻŋāώāϝāĻŧ:
- Sequential: āĻĒāϰā§āϰ operation-āĻāĻŋ āϝāĻĻāĻŋ āĻāĻā§āϰ operation-āĻāϰ result-āĻāϰ āĻāĻĒāϰ āύāĻŋāϰā§āĻāϰ āĻāϰā§, āϤāĻžāĻšāϞā§
awaitāĻāĻāĻāĻžāϰ āĻĒāϰ āĻāĻāĻāĻž āĻāϰāϤ⧠āĻšāϝāĻŧāĨ¤ āĻĒā§āϰāϤāĻŋāĻāĻŋ step-āĻāϰ āϏāĻŽāϝāĻŧ āϝā§āĻ āĻšāϝāĻŧā§ āĻŽā§āĻ āϏāĻŽāϝāĻŧ āĻŦāĻžāĻĄāĻŧā§āĨ¤ - Parallel: operation āĻā§āϞ⧠āĻāĻā§ āĻ
āĻĒāϰā§āϰ āĻāĻĒāϰ āύāĻŋāϰā§āĻāϰāĻļā§āϞ āύāĻž āĻšāϞā§, āϏāĻŦ āĻāĻāϏāĻžāĻĨā§ āĻļā§āϰ⧠āĻāϰā§
Promise.all()(āĻŦāĻžPromise.allSettled()) āĻĻāĻŋāϝāĻŧā§ āĻāĻāϏāĻžāĻĨā§ āĻ āĻĒā§āĻā§āώāĻž āĻāϰāĻž āĻāĻāĻŋāϤāĨ¤ āĻŽā§āĻ āϏāĻŽāϝāĻŧ āϏāĻŦāĻā§āϝāĻŧā§ āϧā§āϰ operation-āĻāĻŋāϰ āϏāĻŽāĻžāύ āĻšāϝāĻŧ, āĻāϞāĻžāĻĻāĻž āĻāϞāĻžāĻĻāĻž āϏāĻŽāϝāĻŧā§āϰ āϝā§āĻāĻĢāϞ āύāϝāĻŧāĨ¤
Code ExampleJavaScriptClick to view details
// â Sequential â āĻ
āĻĒā§āϰāϝāĻŧā§āĻāύā§āϝāĻŧāĻāĻžāĻŦā§ āϧā§āϰ, āĻāĻžāϰāĻŖ posts, user-āĻāϰ āĻāĻĒāϰ āύāĻŋāϰā§āĻāϰ āĻāϰāĻā§ āύāĻž
async function loadSequential() {
const user = await fetchUser(); // ā§Šā§Ļā§Ļms
const posts = await fetchPosts(); // āĻāĻ°ā§ ā§Šā§Ļā§Ļms
return { user, posts }; // āĻŽā§āĻ ~ā§Ŧā§Ļā§Ļms
}
// â
Parallel â dependency āύā§āĻ, āϤāĻžāĻ āĻāĻāϏāĻžāĻĨā§ āĻāĻžāϞāĻžāύ⧠āĻāĻāĻŋāϤ
async function loadParallel() {
const [user, posts] = await Promise.all([fetchUser(), fetchPosts()]);
return { user, posts }; // āĻŽā§āĻ ~ā§Šā§Ļā§Ļms
}
āĻāĻāύ sequential-āĻ āϏāĻ āĻŋāĻ āĻĒāĻāύā§āĻĻ:
Code ExampleJavaScriptClick to view details
// â
āĻāĻāĻžāύ⧠sequential-āĻ āĻāĻāĻŽāĻžāϤā§āϰ āĻāĻĒāĻžāϝāĻŧ, āĻāĻžāϰāĻŖ orders, user.id-āĻāϰ āĻāĻĒāϰ āύāĻŋāϰā§āĻāϰ āĻāϰāĻā§
async function loadDependent() {
const user = await fetchUser(); // āĻāĻā§ user āϞāĻžāĻāĻŦā§
const orders = await fetchOrders(user.id); // āϤāĻžāϰāĻĒāϰ orders
return { user, orders };
}
āĻŦāĻŋāϏā§āϤāĻžāϰāĻŋāϤ pattern (Promise.all, Promise.allSettled, Promise.race, concurrency limiting) āύāĻŋāĻ⧠⧍⧠āύāĻŽā§āĻŦāϰ āĻĒā§āϰāĻļā§āύ⧠āĻāϞā§āĻāύāĻž āĻāϰāĻž āĻšāϝāĻŧā§āĻā§āĨ¤
- Difference between
awaitin a loop vsPromise.all - What is the difference between
Promise.allandPromise.allSettled? - What is
Promise.raceand 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 āĻāϰāϤ⧠āĻšāϞā§āĨ¤
- How does
async.waterfallcompare to native Promise chaining? - What is
async.parallelandasync.series?
async.series â tasks āĻā§āϞ⧠āĻāĻāĻāĻžāϰ āĻĒāϰ āĻāĻāĻāĻž āĻāĻžāϞāĻžāϝāĻŧāĨ¤ āĻāĻāĻāĻŋ āĻļā§āώ āύāĻž āĻšāϞ⧠āĻĒāϰā§āϰāĻāĻŋ āĻļā§āϰ⧠āĻšāϝāĻŧ āύāĻžāĨ¤ āĻāĻāĻāĻŋāϤ⧠error āĻšāϞ⧠āĻŦāĻžāĻāĻŋāĻā§āϞ⧠āĻāϰ āĻāϞ⧠āύāĻžāĨ¤
Code ExampleJavaScriptClick to view details
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 āĻāĻāϏāĻžāĻĨā§ āĻĒāĻžāĻāϝāĻŧāĻž āϝāĻžāϝāĻŧāĨ¤
Code ExampleJavaScriptClick to view details
async.parallel(
[
(callback) => {
setTimeout(() => callback(null, "result1"), 300);
},
(callback) => {
setTimeout(() => callback(null, "result2"), 100);
},
],
(err, results) => {
console.log(results); // ['result1', 'result2']
// āĻŽā§āĻ āϏāĻŽāϝāĻŧ: ~300ms (āϏāĻŦāĻā§āϝāĻŧā§ āĻŦā§āĻļāĻŋ āϏāĻŽāϝāĻŧ āύā§āĻāϝāĻŧāĻž task-āĻāϰ āϏāĻŽāĻžāύ)
},
);
async.series | async.parallel | |
|---|---|---|
| Execution | āĻāĻāĻāĻžāϰ āĻĒāϰ āĻāĻāĻāĻž | āĻāĻāϏāĻžāĻĨā§ |
| āĻŽā§āĻ āϏāĻŽāϝāĻŧ | āϏāĻŦ task-āĻāϰ āϏāĻŽāϝāĻŧā§āϰ āϝā§āĻāĻĢāϞ | āϏāĻŦāĻā§āϝāĻŧā§ āϧā§āϰ task-āĻāϰ āϏāĻŽāϝāĻŧ |
| āĻāĻāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ | āĻāĻāĻāĻŋāϰ output āĻāϰā§āĻāĻāĻŋāϰ input | tasks āĻĒāϰāϏā§āĻĒāϰ independent |
âī¸ How does the async module compare to native Promise.all?â
āĻĻā§āĻā§āϰāĻ āϞāĻā§āώā§āϝ āĻāĻāĻ â āĻāĻāĻžāϧāĻŋāĻ asynchronous task manage āĻāϰāĻž â āĻāĻŋāύā§āϤ⧠approach āĻāϞāĻžāĻĻāĻž:
| āĻŦāĻŋāώāϝāĻŧ | async module | Native Promise / async-await |
|---|---|---|
| Dependency | External npm package āϞāĻžāĻā§ | JavaScript/Node.js-āĻ built-in, āĻāĻŋāĻā§ install āĻāϰāϤ⧠āĻšāϝāĻŧ āύāĻž |
| Callback style | Error-first callback āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠| Promise-based, then/await āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠|
| Control flow | series, parallel, waterfall, queue-āĻāϰ āĻŽāϤ⧠ready-made helper āĻāĻā§ | āĻļā§āϧ⧠Promise.all, Promise.allSettled, Promise.race â āĻāĻāĻŋāϞ flow āύāĻŋāĻā§ āĻāĻ āύ āĻāϰāϤ⧠āĻšāϝāĻŧ |
| Concurrency limiting | async.parallelLimit, async.queue āĻĻāĻŋāϝāĻŧā§ built-in āϏāĻžāĻĒā§āϰā§āĻ | āύāĻŋāĻā§ āϞāĻŋāĻāϤ⧠āĻšāϝāĻŧ, āĻ
āĻĨāĻŦāĻž p-limit-āĻāϰ āĻŽāϤ⧠āĻāϞāĻžāĻĻāĻž library āϞāĻžāĻā§ |
| āĻāϧā§āύāĻŋāĻ codebase-āĻ āĻŦā§āϝāĻŦāĻšāĻžāϰ | āĻāĻŽ â legacy āĻŦāĻž āĻā§āĻŦāĻ complex flow-āϤ⧠| āĻŦā§āĻļāĻŋ â de facto standard |
āϏāĻāĻā§āώā§āĻĒā§: āύāϤā§āύ āĻ ā§āύ⧠Node.js project āĻļā§āϰ⧠āĻāϰāϞ⧠āϏāĻžāϧāĻžāϰāĻŖāϤ native Promise/async-await (Promise.all, Promise.allSettled āĻāϤā§āϝāĻžāĻĻāĻŋ) āϝāĻĨā§āώā§āĻāĨ¤ async module āĻŽā§āϞāϤ āϤāĻāύāĻ āĻŦā§āĻā§ āύā§āĻāϝāĻŧāĻž āĻšāϝāĻŧ āϝāĻāύ legacy callback-based codebase-āĻ āĻāĻžāĻ āĻāϰāϤ⧠āĻšāϝāĻŧ, āĻ
āĻĨāĻŦāĻž waterfall/queue-āĻāϰ āĻŽāϤ⧠built-in concurrency-control helper āĻā§āϞā§āϰ āĻĻāϰāĻāĻžāϰ āĻšāϝāĻŧ āϝā§āĻā§āϞ⧠native Promise API-āϤ⧠āϏāϰāĻžāϏāϰāĻŋ āύā§āĻāĨ¤
đ 27. How do you handle parallel asynchronous operations in Node.js?â
Node.js-āĻ parallel async operation handle āĻāϰāĻžāϰ āϏāĻŦāĻā§āϝāĻŧā§ āϏāĻšāĻ āĻāĻŦāĻ modern āĻāĻĒāĻžāϝāĻŧ āĻšāϞ⧠Promise.all(), Promise.allSettled(), āĻŦāĻž Promise.race() āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻžāĨ¤
- Difference between
awaitin a loop vsPromise.all - What is the difference between
Promise.allandPromise.allSettled?
Promise.all() â āϏāĻŦāĻā§āϞ⧠Promise āϏāĻĢāϞāĻāĻžāĻŦā§ resolve āĻšāϞ⧠āϤāĻŦā§āĻ result āĻĻā§āϝāĻŧāĨ¤ āϝā§āĻā§āύ⧠āĻāĻāĻāĻŋ reject āĻšāϞ⧠āϏāĻžāĻĨā§ āϏāĻžāĻĨā§ āĻĒā§āϰ⧠call āĻāĻŋ reject āĻšāϝāĻŧā§ āϝāĻžāϝāĻŧ āĻāĻŦāĻ āĻŦāĻžāĻāĻŋāĻā§āϞā§āϰ result āĻĒāĻžāĻāϝāĻŧāĻž āϝāĻžāϝāĻŧ āύāĻžāĨ¤
Code ExampleJavaScriptClick to view details
const [user, posts, comments] = await Promise.all([
fetchUser(1),
fetchPosts(1),
fetchComments(1),
]);
// āϤāĻŋāύāĻāĻŋāϰ āϝā§āĻā§āύ⧠āĻāĻāĻāĻŋ fail āĻāϰāϞ⧠āϏāĻŦ āĻŦāĻžāϤāĻŋāϞ
Promise.allSettled() â āϏāĻŦāĻā§āϞ⧠Promise complete āĻšāĻāϝāĻŧāĻž āĻĒāϰā§āϝāύā§āϤ āĻ
āĻĒā§āĻā§āώāĻž āĻāϰā§, āĻā§āĻ reject āĻšāϞā§āĻāĨ¤ āĻĒā§āϰāϤāĻŋāĻāĻŋāϰ āĻāύā§āϝ āĻāϞāĻžāĻĻāĻžāĻāĻžāĻŦā§ status: 'fulfilled' āĻŦāĻž status: 'rejected' āĻāĻžāύāĻž āϝāĻžāϝāĻŧāĨ¤
Code ExampleJavaScriptClick to view details
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.all | Promise.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 āĻāϰ āĻĒāĻžāĻāϝāĻŧāĻž āϝāĻžāϝāĻŧ āύāĻžāĨ¤
Code ExampleJavaScriptClick to view details
const result = await Promise.race([
fetchFromServer1(), // ⧍ā§Ļā§Ļms āϞāĻžāĻāϞā§
fetchFromServer2(), // ā§Ģā§Ļā§Ļms āϞāĻžāĻāϞā§
fetchFromServer3(), // ā§§ā§Ļā§Ļms āϞāĻžāĻāϞ⧠â āĻāĻāĻŋ āĻāĻŋāϤāĻŦā§
]);
// result = server3-āĻāϰ response
āĻāĻāύ useful:
Timeout implement āĻāϰāϤā§:
Code ExampleJavaScriptClick to view details
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):
Code ExampleJavaScriptClick to view details
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 āĻāĻžāĻĄāĻŧāĻž):
Code ExampleJavaScriptClick to view details
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 āĻšāϝāĻŧāĨ¤
Code ExampleJavaScriptClick to view details
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 āĻāϰ⧠āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āϝāĻžāϝāĻŧ:
Code ExampleJavaScriptClick to view details
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 āĻšāĻŦā§āĨ¤
Code ExampleJavaScriptClick to view details
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 āĻšāϝāĻŧā§ āϝāĻžāϝāĻŧāĨ¤
Code ExampleJavaScriptClick to view details
emitter.once("connection", (socket) => {
console.log("āĻĒā§āϰāĻĨāĻŽ connection āĻĒāĻžāĻāϝāĻŧāĻž āĻā§āĻā§");
});
emitter.emit("connection", socket1); // â
āĻāϞāĻŦā§
emitter.emit("connection", socket2); // â āĻāϰ āĻāϞāĻŦā§ āύāĻž
āĻāĻāύ āĻā§āύāĻāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻŦā§āύ:
on | once | |
|---|---|---|
| āĻāϤāĻŦāĻžāϰ āĻāϞ⧠| āĻŦāĻžāϰāĻŦāĻžāϰ | āĻļā§āϧ⧠āĻāĻāĻŦāĻžāϰ |
| āĻāĻāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ | ongoing events (data, message) | one-time events (ready, connection) |
| Manual remove | off() āĻĻāĻŋāϝāĻŧā§ āĻāϰāϤ⧠āĻšāϝāĻŧ | 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-āĻāϰ āĻāĻĻāĻžāĻšāϰāĻŖ:
Code ExampleJavaScriptClick to view details
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 āĻāϰāĻž:
Code ExampleJavaScriptClick to view details
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:
Code ExampleJavaScriptClick to view details
async function fetchData() {
try {
const data = await riskyOperation();
return data;
} catch (err) {
console.error("Async error handled:", err.message);
}
}
Unhandled Promise rejection handle āĻāϰāĻž:
Code ExampleJavaScriptClick to view details
// 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:
Code ExampleJavaScriptClick to view details
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-āĻ āĻĢāĻžāĻāĻ āĻāĻā§āĨ¤
Code ExampleJavaScriptClick to view details
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 āϧāϰā§āύāĻŋāĨ¤
Code ExampleJavaScriptClick to view details
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 āĻāϰāĻž āĻšāϝāĻŧāύāĻŋāĨ¤
Code ExampleJavaScriptClick to view details
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() āύā§āĻ
āĻĻā§āĻā§āϰ āϤā§āϞāύāĻž:
uncaughtException | unhandledRejection | |
|---|---|---|
| Source | Synchronous throw | Promise rejection |
| Callback parameters | (err, origin) | (reason, promise) |
| Node.js default behavior | Process crash | Node.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-āĻ āĻāĻā§āĨ¤ āĻāĻ āĻ
āĻŦāϏā§āĻĨāĻžāϝāĻŧ āĻāĻžāϞāĻŋāϝāĻŧā§ āĻā§āϞā§:
Code ExampleJavaScriptClick to view details
// â āĻ
āϤā§āϝāύā§āϤ āĻŦāĻŋāĻĒāĻā§āĻāύāĻ 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 āĻĻāĻŋāĻā§āĻā§āĨ¤
Code ExampleJavaScriptClick to view details
// â
āϏāĻ āĻŋāĻ 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 āϧāϰāϤ⧠āĻĒāĻžāϰā§āĨ¤
Code ExampleJavaScriptClick to view details
// â
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()-āĻ āĻāϞ⧠āĻāϏā§āĨ¤
Code ExampleJavaScriptClick to view details
// â
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);
});
āĻā§āϰā§āϤā§āĻŦāĻĒā§āϰā§āĻŖ āĻĒāĻžāϰā§āĻĨāĻā§āϝ:
Code ExampleJavaScriptClick to view details
// â 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 ExampleJavaScriptClick to view details
// āĻāĻ code Node.js 15+-āĻ process crash āĻāϰāĻŦā§:
async function fail() {
throw new Error("Rejected!");
}
fail(); // .catch() āύā§āĻ, await āύā§āĻ
// UnhandledPromiseRejection: process exit code 1
āĻā§āĻāĻžāĻŦā§ prevent āĻāϰāĻŦā§āύ:
Code ExampleJavaScriptClick to view details
// â
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 āĻāϰāϞ⧠āϏāĻŦ āĻŦāĻžāϤāĻŋāϞ:
Code ExampleJavaScriptClick to view details
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 āϏāĻžāĻŽāϞāĻžāύā§:
Code ExampleJavaScriptClick to view details
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-āĻāϰ āĻāύā§āϝ:
Code ExampleJavaScriptClick to view details
// 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 āĻāϰāĻž āϏāĻŽā§āĻāĻŦāĨ¤
Code ExampleJavaScriptClick to view details
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 āĻāϰāϤ⧠āĻšāϤā§:
Code ExampleJavaScriptClick to view details
// â āĻāĻžāĻĄāĻŧāĻž AsyncLocalStorage â āϏāĻŦ āĻāĻžāϝāĻŧāĻāĻžāϝāĻŧ manually pass āĻāϰāϤ⧠āĻšāĻā§āĻā§
async function handleRequest(requestId) {
const user = await getUser(requestId); // pass āĻāϰāϤ⧠āĻšāĻā§āĻā§
const data = await fetchData(requestId); // āĻāĻāĻžāύā§āĻ
await saveLog(requestId, user, data); // āĻāĻāĻžāύā§āĻ
}
AsyncLocalStorage āĻĻāĻŋāϝāĻŧā§ āϏāĻŽāĻžāϧāĻžāύ:
Code ExampleJavaScriptClick to view details
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_hooks | AsyncLocalStorage | |
|---|---|---|
| Level | Low-level | High-level |
| Performance | āĻŦā§āĻļāĻŋ overhead | āĻ āύā§āĻ āĻāĻŽ overhead |
| āĻŦā§āϝāĻŦāĻšāĻžāϰā§āϰ āϏāĻšāĻāϤāĻž | āĻāĻāĻŋāϞ | āϏāĻšāĻ |
| Context propagation | Manual | Automatic |
đ 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 āĻāϰā§āĨ¤
Code ExampleJavaScriptClick to view details
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 āĻā§āϤāϰ⧠āĻā§āĻāĻžāĻŦā§ āĻāĻžāĻ āĻāϰā§:
Code ExampleJavaScriptClick to view details
// 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 āĻāϰāϤ⧠āĻšāϝāĻŧāĨ¤
Code ExampleJavaScriptClick to view details
// āĻāĻāĻāĻŋ 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 āĻāϰāϤ⧠āĻšāĻŦā§āĨ¤
Code ExampleJavaScriptClick to view details
// â 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 āĻĨāĻžāĻā§:
Code ExampleJavaScriptClick to view details
// āĻāĻŋāĻā§ 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 āĻāϰāĻž āϝāĻžāϝāĻŧ:
Code ExampleJavaScriptClick to view details
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);