异步编程是现代JavaScript开发的核心组成部分,Promise和async/await是处理异步操作的两种主流方案,合理运用它们可以避免回调地狱,提升代码的可读性和可维护性。在实际开发中,掌握对应的最佳实践能有效减少错误,优化代码性能。

Promise最佳实践
避免回调地狱,链式调用优先
Promise的核心优势是支持链式调用,替代传统的嵌套回调。不要在一个then回调中再手动创建新的Promise,而是直接返回Promise实例实现链式传递。
// 错误示例:嵌套创建Promise
function getUserInfo() {
return new Promise((resolve) => {
fetch('/api/user').then(res => {
resolve(res.json());
});
});
}
// 正确示例:链式返回Promise
function getUserInfo() {
return fetch('/api/user').then(res => res.json());
}
统一错误捕获
Promise的错误可以通过catch方法统一捕获,不要在每个then回调中单独处理错误,避免遗漏。同时要注意,Promise内部的同步错误会被自动捕获,无需额外try catch。
// 错误示例:分散处理错误
fetch('/api/data')
.then(res => {
if (!res.ok) throw new Error('请求失败');
return res.json();
}, err => {
console.log('错误1', err);
})
.then(data => {
console.log(data);
}, err => {
console.log('错误2', err);
});
// 正确示例:统一catch捕获
fetch('/api/data')
.then(res => {
if (!res.ok) throw new Error('请求失败');
return res.json();
})
.then(data => {
console.log(data);
})
.catch(err => {
console.log('统一捕获错误', err);
});
合理使用Promise静态方法
Promise.all适合处理多个并行且相互独立的异步任务,所有任务完成才返回结果;Promise.allSettled可以获取所有任务的最终状态,不管成功失败;Promise.race适合需要超时控制的场景。
// 并行请求多个接口,全部完成再处理
const task1 = fetch('/api/a').then(res => res.json());
const task2 = fetch('/api/b').then(res => res.json());
Promise.all([task1, task2])
.then(([dataA, dataB]) => {
console.log('两个接口数据', dataA, dataB);
})
.catch(err => {
console.log('任意一个接口失败则触发', err);
});
// 超时控制示例
const requestTask = fetch('/api/slow').then(res => res.json());
const timeoutTask = new Promise((_, reject) => {
setTimeout(() => reject(new Error('请求超时')), 3000);
});
Promise.race([requestTask, timeoutTask])
.then(data => console.log('请求成功', data))
.catch(err => console.log('结果', err.message));
async/await最佳实践
避免不必要的await阻塞
async/await会让代码看起来像同步执行,但如果多个异步任务之间没有依赖关系,不要逐个await,否则会串行执行浪费时间,应该并行处理。
// 错误示例:串行执行无依赖的任务
async function loadData() {
const user = await fetch('/api/user').then(res => res.json());
const order = await fetch('/api/order').then(res => res.json());
return { user, order };
}
// 正确示例:并行执行无依赖的任务
async function loadData() {
const userPromise = fetch('/api/user').then(res => res.json());
const orderPromise = fetch('/api/order').then(res => res.json());
const user = await userPromise;
const order = await orderPromise;
return { user, order };
}
正确捕获async/await的错误
async函数返回的Promise错误需要用try catch捕获,或者后续用catch方法捕获,不要忽略错误处理。不要在每个await前都加try catch,尽量统一处理。
// 错误示例:忽略错误捕获
async function getData() {
const data = await fetch('/api/data').then(res => res.json());
return data;
}
// 正确示例:统一try catch捕获
async function getData() {
try {
const data = await fetch('/api/data').then(res => res.json());
return data;
} catch (err) {
console.log('请求失败', err);
return null;
}
}
不要在循环中使用await
在for循环中使用await会导致每次循环都等待上一个异步任务完成,变成串行执行,效率很低。可以先用数组收集所有Promise,再用Promise.all统一处理。
// 错误示例:循环中await串行执行
async function getListData(ids) {
const result = [];
for (const id of ids) {
const data = await fetch(`/api/item/${id}`).then(res => res.json());
result.push(data);
}
return result;
}
// 正确示例:并行处理循环中的异步任务
async function getListData(ids) {
const promiseList = ids.map(id => fetch(`/api/item/${id}`).then(res => res.json()));
return Promise.all(promiseList);
}
通用注意事项
不要在Promise或async函数中返回undefined后还期待后续处理,要明确返回值的类型。如果异步函数没有返回值,可以返回Promise.resolve()表示完成。另外,不要对已经resolved的Promise重复调用resolve或reject,避免逻辑混乱。
在实际项目中,可以根据场景选择Promise或async/await:简单的链式异步操作用Promise更简洁,复杂的多步骤异步逻辑用async/await可读性更高,两者也可以结合使用,发挥各自的优势。
Promiseasync_awaitJavaScript异步编程修改时间:2026-07-05 05:21:11