异步编程是前端开发的家常便饭,但面对 Promise 和 async/await,你是否还在纠结该用哪个?本文用真实案例对比两种异步方法,告诉你如何在项目中灵活选择,让代码既高效又易读。
一、Promise 和 async/await 的本质
- Promise 是一个表示异步操作最终完成(或失败)及其结果的对象。它有三种状态:Pending(进行中)、Fulfilled(已成功)、Rejected(已失败)。Promise 的出现解决了传统回调函数导致的"回调地狱"问题。
- async/await 是基于 Promise 的语法糖,让异步代码看起来更像同步代码。
async
函数返回的是一个 Promise 对象,await
关键字用于等待 Promise 解析。
二、Promise 和 async/await 的对比
1. 代码可读性
- Promise :链式调用,适合简单的异步操作,但嵌套多层
then
时可读性下降。 - async/await:代码更简洁,异步操作看起来像同步代码,适合复杂的异步流程。
2. 错误处理
- Promise :通过
.catch()
捕获错误。 - async/await :通过
try/catch
捕获错误,更符合同步代码的错误处理习惯。
3. 性能
- Promise :适合并行执行多个异步操作,如
Promise.all
。 - async/await :适合串行执行,但多个无依赖的异步操作使用
await
会导致性能降低。
三、实际应用场景
1. 线性异步流程
场景:先登录获取 token,再用 token 获取用户信息,最后加载权限配置。
javascript
// async/await 写法
async function initApp(username, password) {
try {
const token = await login(username, password);
const userInfo = await getUserInfo(token);
const permissions = await getPermissions(userInfo.role);
renderApp(permissions);
} catch (err) {
showError(err);
}
}
为什么用 async/await:逻辑清晰,按顺序执行。
2. 并行执行多个异步操作
场景:同时加载列表数据和筛选条件。
javascript
// Promise 写法
async function loadDashboard() {
const [products, categories] = await Promise.all([
fetchProducts(),
fetchCategories()
]);
renderProducts(products);
renderFilters(categories);
}
为什么用 Promise :Promise.all
并行执行多个异步任务,效率更高。
3. 超时控制
场景:请求超时提示。
javascript
// Promise 写法
function withTimeout(promise, timeoutMs = 3000) {
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('请求超时')), timeoutMs);
});
return Promise.race([promise, timeoutPromise]);
}
为什么用 Promise :Promise.race
实现超时控制。
四、混搭使用
场景:先并行获取基础数据,再串行处理后续逻辑。
javascript
async function buildReport() {
const [users, orders, products] = await Promise.all([
fetchUsers(),
fetchOrders(),
fetchProducts()
]);
const userStats = await calculateUserStats(users);
const orderSummary = await generateOrderSummary(orders, userStats);
const report = await compileReport(orderSummary, products);
return report;
}
为什么混搭:兼顾效率和可读性。
五、避坑指南
- 不要在循环中直接用 await :会导致串行执行,改用
Promise.all
。 - 别忘了 try/catch :async/await 中任何
await
的 Promise reject 都会触发异常。 - 不要把 async 函数当同步函数用:async 函数永远返回 Promise。
六、总结
- Promise:适合并行任务、超时控制、动态数量任务。
- async/await:适合线性流程、条件判断、中断执行。
选择合适的异步方法,让代码既高效又易读。