前端异常捕获需用try/catch包裹await或promise链末尾加.catch(),区分网络错误、http状态错误和业务错误并分类处理,辅以unhandledrejection全局兜底。

前端网络请求的异常捕获不能靠外层 try/catch 包裹调用,因为 fetch、axios 等发起的是异步操作,错误不会同步抛出。关键在于理解 Promise 拒绝(rejection)的传播机制,并在正确位置拦截。
用 try/catch 包裹 await 请求
这是最直观、推荐的方式,适用于 async 函数内部:
- 所有 await 后的 Promise 被拒绝时,会像同步 throw 一样被
catch捕获 - 能统一处理网络失败、JSON 解析错误、业务逻辑校验失败等各类异常
- 注意:必须确保
await的 Promise 确实会 reject —— 原生fetch在网络断开或请求被取消时才 reject,HTTP 错误状态(如 404、500)默认仍 resolve,需手动判断
示例:
async function getUser() {try {
const res = await fetch('/api/user');
if (!res.ok) {
throw new Error(`HTTP ${res.status}: ${res.statusText}`);
}
return await res.json();
} catch (err) {
console.error('获取用户失败', err);
// 可上报、提示用户、返回默认值等
}
}
对 Promise 链使用 .catch()
适用于不写 async/await 的场景,或需要链式处理多个异步步骤:
-
.catch()必须放在 Promise 链末尾,才能捕获前面任意环节的 reject 或 throw - 它会捕获上一个
.then()中抛出的异常、Promise 拒绝、甚至 JSON 解析失败(res.json()失败时也会 reject) - 避免漏掉
.catch(),否则未捕获的 rejection 会触发unhandledrejection全局事件
示例:
fetch('/api/data').then(res => {
if (!res.ok) throw new Error('接口响应异常');
return res.json();
})
.then(data => console.log(data))
.catch(err => console.error('请求链出错', err));
区分网络错误与业务错误
真实场景中,异常类型不同,处理方式也应不同:
- 网络层错误:DNS 失败、连接超时、CORS、fetch 被中止 —— 通常不可恢复,建议提示“网络异常,请检查”
- HTTP 状态错误:401(未登录)、403(无权限)、404(资源不存在)、500(服务端异常)—— 应按状态码做定向处理(如跳转登录页、显示友好提示)
-
业务逻辑错误:后端返回
{ code: 40001, message: "手机号已注册" }—— 属于正常业务流,不应视为“异常”,而应走成功分支解析并提示用户
建议封装统一请求函数,在其中完成状态码判断和错误分类,再抛出不同类型的自定义错误(如 NetworkError、AuthError),便于上层差异化处理。
兜底:监听 unhandledrejection
作为最后一道防线,捕获所有未被 .catch() 或 try/catch 拦截的 Promise 拒绝:
- 在全局添加一次监听即可:
window.addEventListener('unhandledrejection', event => { ... }) - 适合做错误日志上报、监控告警,但不能替代主动错误处理,因为此时已失去上下文(比如不知道是哪个 API、什么参数出错)
- 可调用
event.preventDefault()阻止控制台报错,但不建议隐藏问题,而应推动补全缺失的错误处理
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











