精准捕获async函数中特定类型错误需识别错误来源并区分性质:利用error.name、status等字段区分原生与业务错误,用instanceof判断自定义错误类,对http状态码和业务code显式校验,配合全局unhandledrejection兜底上报。

捕获 async 函数中特定类型错误,关键不是“拦住所有错误”,而是识别错误来源、区分错误性质,并按需响应。JavaScript 中的 async 函数抛出的错误本质是 Promise rejection,但错误对象本身可携带类型信息(如 name、code、status、message 模式等),利用这些特征就能实现精准捕获。
根据 error.name 和自定义类型字段做判断
原生错误(如 TypeError、SyntaxError、AbortError)和业务错误(如 API 返回的 { code: 401, message: "Unauthorized" })通常可通过 error.name 或结构化字段快速区分。
- 网络中断或跨域失败常触发
TypeError(如 "Failed to fetch") - fetch 响应非 2xx 时,手动 throw 的错误建议统一设
name: 'HttpError' - Axios 等库会附加
error.response?.status、error.code(如 'ECONNABORTED')
示例:
async function fetchUser() {
try {
const res = await fetch('/api/user');
if (!res.ok) {
const err = new Error(`HTTP ${res.status}`);
err.name = 'HttpError';
err.status = res.status;
throw err;
}
return await res.json();
} catch (err) {
if (err.name === 'HttpError') {
if (err.status === 401) handleAuthFailure();
else if (err.status >= 500) showRetryButton();
} else if (err.name === 'TypeError') {
showNetworkError();
}
}
}
用 instanceof 区分自定义错误类
对高频、需统一处理的错误场景(如登录过期、权限不足、限流拒绝),推荐定义继承 Error 的类,便于用 instanceof 精准识别。
- 避免仅靠字符串匹配 message,易受文案变更影响
- 构造时可附带额外上下文,如
new AuthExpiredError({ redirectUrl: '/login' }) - 多个 await 调用可分别 throw 不同子类,catch 中逐级判断
示例:
class AuthExpiredError extends Error {
constructor(options = {}) {
super('登录已过期');
this.name = 'AuthExpiredError';
this.redirectUrl = options.redirectUrl || '/login';
}
}
async function loadProfile() {
try {
await fetchWithAuth('/api/profile');
} catch (err) {
if (err instanceof AuthExpiredError) {
window.location.href = err.redirectUrl;
} else if (err instanceof RateLimitError) {
showRateLimitTip();
}
}
}
按 HTTP 状态码或业务 code 分支处理
服务端返回的结构化错误(如 { code: 1002, msg: "余额不足" })不应被当作异常丢弃,而应在 await 后显式检查,再分类响应。
- fetch/axios 的
response.json()成功后,仍需判断 data.code 是否为 0 或 success 字段 - 把“业务失败”和“技术异常”分开:前者是预期流程分支,后者才是需要 try/catch 的意外
- 可封装通用校验函数,如
checkApiResult(data),内部 throw 对应错误类
示例:
async function pay(orderId) {
try {
const res = await fetch('/api/pay', { method: 'POST', body: orderId });
const data = await res.json();
// 技术层成功,业务层可能失败
if (data.code !== 0) {
switch (data.code) {
case 2001: throw new InsufficientBalanceError(data.msg);
case 2002: throw new InventoryShortageError(data.msg);
default: throw new BusinessError(data.msg);
}
}
return data;
} catch (err) {
if (err instanceof InsufficientBalanceError) {
showTopUpDialog();
} else if (err instanceof BusinessError) {
showToast(err.message);
}
}
}
全局兜底 + 错误分类上报
即使做了精细捕获,仍有未覆盖路径(如第三方 SDK 抛错、未 await 的 Promise)。需设置 window.onunhandledrejection 兜底,并按错误特征打标上报,便于后续归因。
- 监听 unhandledrejection 事件,提取 error.name、stack、URL、时间戳
- 对 network error、script error、promise rejection 分类标记
- 避免在兜底逻辑中执行复杂操作(如弹窗),优先记录日志并静默降级
示例:
window.onunhandledrejection = (event) => {
const err = event.reason;
const category = err.name
? (err.name.includes('Error') ? 'js-error' : 'unknown')
: 'promise-reject';
reportError({
category,
message: err.message,
stack: err.stack,
url: location.href
});
};Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











