JavaScript中通过自定义AppError类封装错误码与提示,结合映射表和全局异常处理器(如unhandledrejection、error事件或框架错误边界),统一响应并展示友好文案,同时在请求层自动注入错误码,实现无需手动try/catch的标准化异常处理。

在 JavaScript 中,通过自定义错误码实现全局异常处理并返回友好提示,核心思路是:统一抛出带 code 和 message 的错误对象,再在全局捕获处(如 unhandledrejection、error 事件或框架的错误边界)解析 code,映射为用户能看懂的提示文案。
定义结构化错误类
避免直接 throw 字符串或原生 Error,封装一个支持错误码的类:
class AppError extends Error {
constructor(code, message, data = null) {
super(message);
this.name = 'AppError';
this.code = code; // 如 'USER_LOGIN_FAILED', 'NETWORK_TIMEOUT'
this.message = message; // 默认提示(开发用)
this.data = data; // 可选附加信息,如错误字段名、重试建议等
this.timestamp = Date.now();
}
}
// 使用示例
throw new AppError('AUTH_TOKEN_EXPIRED', '登录已过期,请重新登录');
建立错误码与友好提示的映射表
把错误码和面向用户的文案分离,便于多语言和统一维护:
const ERROR_MESSAGES = {
'NETWORK_ERROR': '网络开小差了,请检查网络后重试',
'AUTH_TOKEN_EXPIRED': '登录状态已失效,请重新登录',
'USER_NOT_FOUND': '账号不存在,请确认输入是否正确',
'VALIDATION_FAILED': '提交信息有误,请检查标红项',
'SERVER_BUSY': '服务暂时繁忙,请稍后再试',
'DEFAULT': '操作失败,请稍后重试'
};
function getFriendlyMessage(code) {
return ERROR_MESSAGES[code] || ERROR_MESSAGES.DEFAULT;
}
在全局异常处理器中统一响应
根据运行环境选择捕获方式,提取 code 并展示提示:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
浏览器环境(全局未捕获错误):
window.addEventListener('error', (e) => { ... })主要捕获同步脚本错误;window.addEventListener('unhandledrejection', (e) => { ... })捕获 Promise 拒绝且未 catch 的错误。 -
React(错误边界):在
componentDidCatch或useEffect+try/catch中判断error.code,触发 toast 或 modal 提示。 -
Vue(errorHandler):配置
app.config.errorHandler,检查err.code后调用 $message 或 $notify。
示例(通用浏览器捕获):
window.addEventListener('unhandledrejection', (event) => {
const err = event.reason;
if (err instanceof AppError) {
showUserToast(getFriendlyMessage(err.code), { type: 'error' });
} else {
// 非自定义错误,可降级为默认提示或上报
showUserToast(getFriendlyMessage('DEFAULT'));
}
event.preventDefault();
});
配合请求层自动注入错误码
在 axios/fetch 封装中,对响应错误做标准化处理:
// axios 示例
axios.interceptors.response.use(
res => res,
error => {
const { response } = error;
if (response?.status === 401) {
return Promise.reject(new AppError('AUTH_TOKEN_EXPIRED', '登录已过期'));
}
if (response?.data?.code) {
// 后端返回 { code: 'USER_LOCKED', message: '...' }
return Promise.reject(new AppError(response.data.code, response.data.message));
}
return Promise.reject(new AppError('NETWORK_ERROR', '请求失败'));
}
);
这样业务层只需 await api.login(...),异常自然落入全局处理器,无需每个地方手动 try/catch。
不复杂但容易忽略的是:错误码命名要语义清晰、全大写+下划线,提示文案要聚焦用户动作(“请重新登录”优于“认证失败”),并且所有抛错路径都走同一类——否则全局处理器就形同虚设。

















