JavaScript异步编程:告别回调地狱的优雅方案
痛点与演进
回调嵌套曾是JS异步编程的噩梦。随着Promise和async/await的普及,我们可以用同步逻辑写异步代码。本文分享三种进阶技巧:
1. Promise链式操作:扁平化异步流程
用.then()
串联操作,替代嵌套回调:
// 传统回调嵌套
getUser(userId, (user) => {
getOrders(user.id, (orders) => {
processOrders(orders); // 深度嵌套
});
});
// Promise链式调用
getUser(userId)
.then(user => getOrders(user.id))
.then(orders => processOrders(orders))
.catch(error => handleError(error)); // 单一错误处理
2. async/await:同步风格的异步代码
用async
函数+await
关键字消除.then()
链:
async function processUserData(userId) {
try {
const user = await getUser(userId);
const orders = await getOrders(user.id);
return processOrders(orders); // 类似同步代码结构
} catch (error) {
handleError(error);
}
}
3. 并行优化:用Promise.all加速
互不依赖的异步任务并行执行:
// 顺序执行(慢)
const user = await getUser();
const posts = await getPosts();
// 并行执行(快)
const [user, posts] = await Promise.all([
getUser(),
getPosts()
]); // 两个请求同时发起
4. 错误处理进阶
结合catch
与条件重试:
async function fetchWithRetry(url, retries = 3) {
try {
return await fetch(url);
} catch (err) {
if (retries > 0) {
await delay(1000); // 等待1秒重试
return fetchWithRetry(url, retries - 1);
}
throw new Error(`请求失败: ${
url}`);
}
}
最佳实践
- 始终用
try/catch
包裹await
- 避免在循环中无脑使用
await
(需并行时用Promise.all
) - 第三方库推荐:
axios
(请求)、p-limit
(并发控制)
掌握这些技巧,让异步代码如同步般清晰!
提示:完整示例代码见 [CodeSandbox 链接]