Difficulty: Intermediate
What is callback hell? How do Promises and async/await solve it?
Callback hell (also called the "pyramid of doom") occurs when multiple asynchronous operations are nested inside callbacks, making the code deeply indented and hard to read.
Evolution of async patterns: 1. Callbacks: Simple but leads to nesting and error handling issues 2. Promises: Chain .then() calls, centralized error handling with .catch() 3. Async/await: Synchronous-looking code, try/catch for errors
Async/await is syntactic sugar over Promises and is the preferred modern approach.
// Callback Hell (the pyramid of doom)
getUser(id, function(err, user) {
if (err) return handleError(err);
getOrders(user.id, function(err, orders) {
if (err) return handleError(err);
getDetails(orders[0].id, function(err, details) {
if (err) return handleError(err);
console.log(details);
});
});
});
// Promise chain (flat)
getUser(id)
.then(user => getOrders(user.id))
.then(orders => getDetails(orders[0].id))
.then(details => console.log(details))
.catch(handleError);
Promises flatten the nesting. Each .then() returns a new Promise, and a single .catch() handles all errors.
async function getShippingInfo(userId) {
try {
const user = await getUser(userId);
const orders = await getOrders(user.id);
const details = await getDetails(orders[0].id);
console.log(details);
return details;
} catch (err) {
handleError(err);
}
}
// Parallel execution when operations are independent
async function loadDashboard() {
const [user, settings, notifications] = await Promise.all([
fetchUser(),
fetchSettings(),
fetchNotifications()
]);
console.log(user, settings, notifications);
}
Async/await reads like synchronous code. Use Promise.all for independent parallel operations.
Callbacks, Callback Hell, Promises, Async/Await