自定义 async 函数错误处理的核心是主动控制“错误识别—分类—传递—响应”链条,通过语义化错误子类(如 networkerror、apierror)、统一拦截增强、可选恢复策略的包装函数及分层错误流向实现可读、可路由、可恢复的错误管理。

自定义 async 函数中的异步错误处理机制,核心是把“错误识别—分类—传递—响应”这一链条控制在自己手里,而不是依赖默认的 throw + try/catch 被动捕获。关键不在于写更多 catch,而在于让错误更可读、可路由、可恢复。
定义语义清晰的错误类
原生 Error 缺乏上下文和类型标识,容易导致错误处理逻辑混杂。建议为不同场景创建继承自 Error 的子类:
- NetworkError:封装 fetch 失败、超时、连接中断等底层通信问题
-
ApiError:对应 HTTP 状态码非 2xx(如 401、404、500),附带
status和body - ValidationError:数据校验失败,含字段名与具体规则
-
TimeoutError:显式包装
AbortController触发的中断
示例:
class ApiError extends Error {
constructor(message, status, response) {
super(`${message} (HTTP ${status})`);
this.name = 'ApiError';
this.status = status;
this.response = response;
}
}
统一错误拦截与增强
在每个关键 await 前插入中间层,自动识别异常并转换为结构化错误:
- 对
fetch结果做res.ok检查,手动throw new ApiError(...) - 用
Promise.race([fetch(), timeout(8000)])控制超时,并抛出TimeoutError - 对
response.json()包裹try/catch,捕获SyntaxError并转为ParseError
这样所有异步操作最终抛出的都是你定义的错误类型,后续处理就能按类分流。
支持可选恢复策略的错误包装函数
避免每个 async 函数都重复写 try-catch,封装一个高阶函数,让调用方声明容错行为:
- 重试:对网络类错误自动重试 2–3 次(指数退避)
- 降级:失败时返回缓存、静态默认值或空对象
- 静默忽略:仅记录日志,不中断主流程(如埋点上报)
示例用法:
const user = await safeFetch('/api/user', {
retry: true,
fallback: { id: -1, name: '游客' }
});
错误流向分层控制
不同层级承担不同职责,避免错误“一锅端”:
-
业务层:用
try/catch处理需用户感知的错误(如登录失败弹提示) -
服务层:统一用
.catch()拦截 Promise 链末尾,做日志上报和监控埋点 -
全局兜底:监听
unhandledrejection,捕获漏网之鱼,防止白屏或静默失败
注意:全局监听不能替代主动处理,它只用于报警和补救,不是主力方案。











