应明确异常类型边界,优先通过构造函数名或自定义属性(如name、code)识别error实例,避免字符串匹配;在await链中用instanceof或属性判断分类处理;封装isautherror等工具函数提升复用性;配合unhandledrejection全局监听兜底。

明确异常类型边界,先区分“谁抛的”
JavaScript 中没有原生的“业务异常类型系统”,所以过滤的前提是——异常必须可识别。常见来源有三类:
- fetch 返回非 2xx 状态时手动 throw 的 Error(如
throw new Error(`HTTP ${res.status}`)) - 服务端返回结构化错误(如
{ code: 'AUTH_EXPIRED', message: '登录已过期' }),需在解析后主动转为 Error - 自定义业务错误类(推荐):比如
class AuthError extends Error { constructor(msg) { super(msg); this.name = 'AuthError'; } }
只要抛出的是 Error 实例,且 err.constructor.name 或 err.name 能稳定标识语义,后续过滤才有依据。
在 await 链中做类型判断,不依赖字符串匹配
用 try/catch 包裹 await 操作后,在 catch 块里按构造函数名或自定义属性分类处理:
- ✅ 推荐:
if (err instanceof AuthError)或err.name === 'AuthError' - ✅ 对服务端错误对象:
if (err.code === 'PERMISSION_DENIED')(前提是统一包装过) - ❌ 避免:
err.message.includes('expired')—— 消息易变、多语言下失效
示例:
try {
const res = await fetch('/api/order', { method: 'POST' });
if (!res.ok) {
const data = await res.json();
throw Object.assign(new Error(data.message), data); // 补充 code/status
}
return await res.json();
} catch (err) {
if (err.name === 'AuthError' || err.code === 'TOKEN_INVALID') {
redirectToLogin();
} else if (err.code === 'INSUFFICIENT_BALANCE') {
showTopupModal();
} else {
notifyUser('提交失败,请稍后重试');
}
}
}
封装通用过滤工具,避免重复写判断逻辑
把类型判断抽成可复用函数,提升一致性:
-
isAuthError(err):检查是否为认证类异常(兼容实例、name、code 多种形态) -
isNetworkError(err):基于err.constructor.name === 'TypeError'判定网络层失败 -
isBusinessCode(err, code):统一取err.code或err.response?.code
这样业务函数里就干净了:
try {await uploadFile(file);
} catch (err) {
if (isAuthError(err)) handleAuth();
else if (isBusinessCode(err, 'FILE_TOO_LARGE')) showFileSizeTip();
else throw err; // 其他异常继续上抛
}
配合全局兜底,确保漏网异常不静默
局部过滤再细,也难保 100% 覆盖。因此必须设置最后防线:
- 浏览器中监听
unhandledrejection,打印日志并上报event.reason - Node.js 中监听
process.on('unhandledRejection') - 关键流程(如支付)可在顶层加
.catch(console.error),防止 Promise 悬空
注意:全局监听只用于发现和报警,不能替代业务层的精准过滤与响应。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











