async/await让JavaScript异步编程变得更加直观和优雅。然而,在处理错误时,这种语法糖也隐藏了许多容易被忽视的陷阱。作为一名经历过无数深夜紧急修复的开发者,分享下生产环境中亲身经历的5个async/await错误处理陷阱,以及如何避免它们。
陷阱一:忘记使用try/catch捕获错误
最常见也最基础的错误是完全忘记处理异步操作中可能发生的异常。
async function fetchUserData(userId) {
const response = await fetch(`/api/users/${userId}`);
const userData = await response.JSON(); // 如果响应不是有效JSON会抛出错误
return userData;
}
这段代码在遇到网络错误、服务器错误或无效JSON时会直接抛出未捕获的异常,可能导致整个应用崩溃。
正确做法:
async function fetchUserData(userId) {
try {
const response = await fetch(`/api/users/${userId}`);
const userData = await response.json();
return userData;
} catch (error) {
console.error(`获取用户数据失败: ${error.message}`);
// 返回默认值或重新抛出错误
throw new Error(`获取用户ID ${userId} 的数据失败: ${error.message}`);
}
}
陷阱二:在Promise链中丢失错误
当混合使用async/await和.then()/.catch()链式调用时,错误处理会变得混乱。
async function processData() {
const rawData = await fetchData();
// 错误:以下的错误不会被当前函数的try/catch捕获
processResult(rawData).then(result => {
// 使用结果...
});
}
正确做法:
async function processData() {
try {
const rawData = await fetchData();
// 方法一:在链中添加错误处理
processResult(rawData)
.then(result => {
// 使用结果...
})
.catch(error => {
console.error("处理结果时出错:", error);
});
// 方法二(更好):完全使用await
const result = await processResult(rawData);
// 使用结果...
} catch (error) {
console.error("处理数据失败:", error);
}
}
陷阱三:在循环中的错误处理不当
在循环中使用async/await时,错误处理尤其复杂。
一个项目的错误会中断整个处理流程,这可能不是你想要的行为。
正确做法:
或者使用Promise.allSettled处理并行操作:
陷阱四:不处理异步函数中的同步错误
一个常见误解是认为try/catch只能捕获await表达式的错误,而忽略了同步代码也会抛出错误。
正确做法:
陷阱五:未考虑await表达式返回的Promise状态
await表达式可能返回已解决的Promise,但其值可能表示错误状态。
正确做法:
async function fetchResource() {
try {
const response = await fetch('/api/resource');
if (!response.ok) {
throw new Error(`API错误: ${response.status} ${response.statusText}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error("获取资源失败:", error);
throw error;
}
}
欢迎补充。