JavaScript 异步处理
Promise 和 Async/Await 都是 JavaScript 中处理异步操作的机制,但它们有不同的语法特点和适用场景。
下面通过一个业务逻辑来进行比较。
这个业务场景是:依次调用3个API,获取用户数据→获取订单数据→更新用户活跃时间,并处理可能的错误。
语法比较
Promise 写法:👇
function getUserAndUpdateActivity(userId) {
return fetchUser(userId)
.then((user) => {
console.log("User data:", user);
return fetchOrders(user.id);
})
.then((orders) => {
console.log("User orders:", orders);
return updateLastActive(userId);
})
.then(() => {
console.log("User activity updated");
return "All operations completed";
})
.catch((error) => {
console.error("Error in operation:", error);
throw error; // 可以重新抛出或处理错误
});
}
// 使用示例
getUserAndUpdateActivity(123)
.then((finalResult) => console.log(finalResult))
.catch((err) => console.error("Final error:", err));
Async/Await 写法:👇
async function getUserAndUpdateActivity(userId) {
try {
const user = await fetchUser(userId);
console.log("User data:", user);
const orders = await fetchOrders(user.id);
console.log("User orders:", orders);
await updateLastActive(userId);
console.log("User activity updated");
return "All operations completed";
} catch (error) {
console.error("Error in operation:", error);
throw error; // 可以重新抛出或处理错误
}
}
// 使用示例(与Promise版本相同)
getUserAndUpdateActivity(123)
.then((finalResult) => console.log(finalResult))
.catch((err) => console.error("Final error:", err));
对比分析
async/await 是 Promise 之上的语法糖。它为编写异步代码提供了一种更简洁的方法,使其更易于阅读和编写。使用 async/await,可以编写看起来与同步代码相似的异步代码,而且它在引擎盖下使用了 Promise。
方面 | Promise.then() | async/await |
---|---|---|
代码结构 | 横向延伸,链式调用 | 纵向延伸,类似同步代码 |
可读性 | 嵌套层次多时较难阅读 | 顺序执行,逻辑清晰 |
错误处理 | .catch() 处理整个链的错误 | try-catch 块可以精确控制错误范围 |
变量共享 | 需要串联变量(通过 return 传递) | 可以在同一作用域共享变量 |
调试体验 | 调试器难以跟踪then链的执行流程 | 可以像同步代码一样逐行调试 |
并行操作 | 需要 Promise.all 显式处理 | 可以结合 Promise.all 使用 |
返回结果 | 必须显式 return 值(否则传给then的是undefined) | 自动包装为 Promise |
并行优化版本
Promise 写法:👇
const fetchInParallel = (userId: number): Promise<[User, Order[]]> => {
// 同时发起多个请求
const userPromise: Promise<User> = fetchUser(userId);
const ordersPromise: Promise<Order[]> = fetchOrders(userId);
// 使用 Promise.all 并行等待
return Promise.all([userPromise, ordersPromise]).then(([user, orders]) => {
console.log(`并行获取结果: ${user.name} 有 ${orders.length} 个订单`);
return [user, orders]; // 返回元组类型
});
};
// 使用示例
fetchInParallel(123).then(([user, orders]) => {
console.log("最终数据:", user, orders);
});
Async/Await 写法:👇
const optimizedFlow = async (userId: number): Promise<[User, Order[]]> => {
try {
const [user, orders] = await Promise.all([
fetchUser(userId),
fetchOrders(userId), // 假设不需要等待用户数据
]);
await updateLastActive(userId);
return [user, orders]; // 返回元组类型
} catch (error) {
console.error("Parallel flow failed:", error);
throw error;
}
};
// 使用示例
optimizedFlow(123).then(([user, orders]) => {
console.log("最终数据:", user, orders);
});
JavaScript 异步处理
http://guoguo.host/blog/p/62f72e62.html