Callbacks
// Traditional callback pattern\nfunction readFile(path, callback) {\n fs.readFile(path, 'utf8', (err, data) => {\n if (err) return callback(err);\n callback(null, data);\n });\n}\n\n// Callback hell (pyramid of doom)\ngetUser(id, (err, user) => {\n getPosts(user.id, (err, posts) => {\n getComments(posts[0].id, (err, comments) => {\n console.log(comments);\n });\n });\n});
Promises
// Creating a promise\nconst readFile = (path) => {\n return new Promise((resolve, reject) => {\n fs.readFile(path, 'utf8', (err, data) => {\n if (err) reject(err);\n else resolve(data);\n });\n });\n};\n\n// Promise chaining\ngetUser(id)\n .then(user => getPosts(user.id))\n .then(posts => getComments(posts[0].id))\n .then(comments => console.log(comments))\n .catch(err => console.error(err));\n\n// Promise.all - parallel execution\nconst [user, posts] = await Promise.all([\n getUser(id),\n getPostsByUser(id),\n]);\n\n// Promise.race - first to resolve\nconst result = await Promise.race([\n fetch('/api/data'),\n timeout(5000),\n]);
Examples
// Simulating async operations with Promises
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
async function fetchUser(id) {
await delay(100);
return { id, name: 'Alice' };
}
async function fetchOrders(userId) {
await delay(100);
return [{ id: 1, total: 50 }, { id: 2, total: 30 }];
}
// Sequential
const user = await fetchUser(1);
const orders = await fetchOrders(user.id);
console.log(`${user.name} has ${orders.length} orders`);
// Parallel (independent calls)
const [products, categories] = await Promise.all([
fetch('/api/products'),
fetch('/api/categories'),
]);
console.log('Products:', products);
console.log('Categories:', categories);