Dùng async/await để giải quyết callback hell — code đọc như synchronous, try/catch natural; Promise.all() cho parallel thay vì await trong for loop.
- Callback hell (pyramid of doom) — ví dụ thực:
fs.readFile('a.txt', (err, data) => { if(err) throw err; db.query(data, (err, rows) => { if(err) throw err; sendEmail(rows[0], (err) => { if(err) throw err; console.log('done') }) }) })— 3 cấp lồng nhau, error handling lặp lại, logic khó theo dõi. - Giải pháp Promise chaining:
readFile('a.txt').then(data => db.query(data)).then(rows => sendEmail(rows[0])).catch(err => console.error(err))— flat hơn nhưng còn awkward với multi-value. - Giải pháp async/await:
try { const data = await readFile('a.txt'); const rows = await db.query(data); await sendEmail(rows[0]); } catch(err) { console.error(err); }— đọc như synchronous code, try/catch natural. - Error propagation khác nhau: callback phải check
errmỗi cấp thủ công, một missed check = silent failure; Promise/async throw tự động bubble up đến .catch/try-catch. - Lưu ý async/await:
awaittrong vòng lặpfor...ofsẽ chạy sequential — dùngPromise.all(items.map(item => process(item)))để parallel.
Use async/await to solve callback hell — code reads like synchronous, natural try/catch; use Promise.all() for parallel operations instead of await in a for loop.
- Callback hell (pyramid of doom) — real example:
fs.readFile('a.txt', (err, data) => { if(err) throw err; db.query(data, (err, rows) => { if(err) throw err; sendEmail(rows[0], (err) => { if(err) throw err; console.log('done') }) }) })— 3 levels of nesting, repeated error handling, logic hard to follow. - Promise chaining solution:
readFile('a.txt').then(data => db.query(data)).then(rows => sendEmail(rows[0])).catch(err => console.error(err))— flatter but still awkward with multi-value passing. async/await solution:try { const data = await readFile('a.txt'); const rows = await db.query(data); await sendEmail(rows[0]); } catch(err) { console.error(err); }— reads like synchronous code, natural try/catch. - Error propagation differences: callbacks must manually check
errat every level — one missed check means silent failure; Promise/async throws automatically bubble up to .catch/try-catch.
Pitfall: await inside a for...of loop runs sequentially — use Promise.all(items.map(item => process(item))) for parallel execution.