在 async 函数中捕获网络异常,必须在内部对可能 reject 的 await 表达式使用 try-catch;直接外部包裹无效,因 fetch 等返回 promise,错误发生在 await 后续处理(如 res.ok 判断、res.json() 解析)或网络中断时;事件处理器需显式处理 promise 结果,避免 unhandled rejection;按需选择 try-catch 或 .catch 链式处理以平衡健壮性与简洁性。

在 async 函数中处理网络异常,关键不是“用不用 try-catch”,而是“在哪用、怎么用才真正起作用”。直接在外面包一层 try-catch 调用 async 函数,几乎捕不到网络错误——因为 async 返回的是 Promise,而网络请求失败(比如 fetch 超时、404、500、JSON 解析失败)触发的是 Promise reject,不是同步抛错。
网络异常实际发生的位置
常见网络异常并不来自 await fetch(...) 这一行本身(它通常不会同步报错),而是来自:
-
fetch 返回的 response 不 ok(如 status=404/500),需手动
throw new Error() -
await response.json() —— 如果后端返回非 JSON 内容或格式错误,会抛出
SyntaxError - 网络中断、DNS 失败、CORS 拒绝 —— 这些会让 fetch() 返回的 Promise 直接 reject
必须在 async 函数内部用 try-catch 包 await 表达式
只有把可能出错的 await 语句放进 try 块,才能捕获对应 Promise 的拒绝值。例如:
✅ 正确写法:
async function fetchUser() {
try {
const res = await fetch('/api/user');
if (!res.ok) {
throw new Error(`HTTP ${res.status}`);
}
const data = await res.json(); // 这里也可能 SyntaxError
return data;
} catch (err) {
console.error('网络请求失败:', err.message);
// 可统一上报、提示用户、返回默认值等
return null;
}
}
事件处理器中不能只调用不处理返回值
像 <button onclick="fetchUser()"></button> 这种写法很危险:函数执行后返回的 Promise 被丢弃,一旦 reject 就变成 unhandled rejection,控制台报错且无感知。
✅ 推荐做法:
- 用
addEventListener+async回调,在内部 try-catch - 或显式链式调用
.catch(),尤其适合非 async 环境
示例:
btn.addEventListener('click', async () => {
try {
const user = await fetchUser();
render(user);
} catch (err) {
showNotify('加载失败,请重试');
}
});
按需选择更轻量的错误处理方式
不是每个网络请求都值得写一整套 try-catch。如果只是更新 loading 状态、失败后静默兜底,可用 Promise 链式 .catch:
function fetchWithLoading(url) {
setLoading(true);
return fetch(url)
.then(res => {
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
})
.catch(err => {
console.warn('请求异常,使用缓存', err);
return getCachedData(); // 或返回默认值
})
.finally(() => setLoading(false));
}
这种写法避免了业务逻辑被 try-catch 块割裂,也更易复用。











