JavaScript 异步编程详解
JavaScript 是单线程语言,但通过异步编程机制,可以高效地处理 I/O 操作、网络请求等耗时任务。
回调函数 (Callback)
最传统的异步处理方式:
1 2 3 4 5 6 7 8 9 10 11 12 13
| function fetchData(callback) { setTimeout(() => { callback(null, { name: 'Alice', age: 25 }); }, 1000); }
fetchData((err, data) => { if (err) { console.error('Error:', err); return; } console.log('Data:', data); });
|
回调地狱问题
1 2 3 4 5 6 7 8
| getUserInfo(userId, (err, user) => { getOrders(user.id, (err, orders) => { getOrderDetails(orders[0].id, (err, details) => { }); }); });
|
Promise
ES6 引入的 Promise 优雅地解决了回调地狱:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function fetchUser(id) { return new Promise((resolve, reject) => { setTimeout(() => { resolve({ id, name: 'Alice' }); }, 1000); }); }
fetchUser(1) .then(user => getOrders(user.id)) .then(orders => getOrderDetails(orders[0].id)) .then(details => console.log(details)) .catch(err => console.error(err));
|
Promise 常用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Promise.all([fetchUser(1), fetchUser(2), fetchUser(3)]) .then(users => console.log('All users:', users));
Promise.race([fetchFromAPI1(), fetchFromAPI2()]) .then(result => console.log('Fastest:', result));
Promise.allSettled([task1(), task2(), task3()]) .then(results => { results.forEach(result => { console.log(result.status, result.value || result.reason); }); });
|
Async / Await
ES2017 带来了更直观的异步写法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| async function getUserData(userId) { try { const user = await fetchUser(userId); const orders = await getOrders(user.id); const details = await getOrderDetails(orders[0].id); return details; } catch (err) { console.error('Error:', err); throw err; } }
async function fetchAllUsers() { const [user1, user2, user3] = await Promise.all([ fetchUser(1), fetchUser(2), fetchUser(3) ]); return { user1, user2, user3 }; }
|
总结
| 方式 |
优点 |
缺点 |
| Callback |
简单直接 |
回调地狱 |
| Promise |
链式调用,可组合 |
代码仍有一定复杂度 |
| Async/Await |
代码最清晰 |
需要 try/catch |
在实际开发中,推荐使用 async/await 配合 Promise 来处理异步操作,代码更清晰、易维护。
下一篇将介绍 JavaScript 事件循环机制,帮助你从原理层面理解异步编程!