Files
lucky_shop/common/js/http-error.js
2026-07-20 18:00:04 +08:00

101 lines
3.8 KiB
JavaScript

/**
* 通用网络/接口错误分类器
*
* 适用场景:
* - uniapp 各端统一错误分类(diy.js / 商品 / 订单 / 自定义页面等)
* - 任意传入 {statusCode, errMsg, message} 形式错误对象的位置
*
* 设计要点:
* 1) 与 Vue / $lang 解耦:不调用任何 i18n 函数,只返回分类结果 + 原始错误字段
* 调用方拿到 type 后,自行决定使用 $lang('http.timeout') / $lang('http.serverError')
* 或其它命名空间的文案,完全保持各模块原有的 key 命名习惯
* 2) 通用网络/接口错误统一映射到 common.http.* 命名空间:
* - http.networkError: 通用网络异常(兜底)
* - http.timeout: 请求超时
* - http.serverError: 服务器错误(5xx)
* - http.notFound: 接口不存在(404)
* - http.auth: 无访问权限(401/403)
* - http.unknown: 其他非 2xx
* 3) 兼容多种错误对象形态:
* - uniapp request: { statusCode, errMsg, data }
* - axios: { response: { status }, message }
* - fetch / 原生: { message, name }
*
* @param {Object|string} err 错误对象或后端业务消息字符串
* @returns {{ type: string, statusCode?: number, errMsg?: string, raw?: any }}
* - type 取值:
* 'business' - 后端返回的业务消息字符串(已透传到 raw)
* 'empty' - 错误对象为空
* 'notFound' - HTTP 404
* 'server' - HTTP 5xx
* 'auth' - HTTP 401 / 403
* 'request' - 其它非 2xx 状态码
* 'timeout' - errMsg 含 timeout
* 'network' - errMsg 含 connect / network / fail
* 'unknown' - 无法分类
* - statusCode: 若有则原样返回
* - errMsg: 归一后的原始消息
* - raw: 原始输入,方便调用方进一步处理
*/
export function classifyHttpError(err) {
// 1) 无错误对象
if (!err) {
return { type: 'empty', raw: err };
}
// 2) 后端直接返回的业务消息(字符串)
if (typeof err === 'string') {
return { type: 'business', raw: err };
}
// 3) 字段归一(兼容 uni / axios / 原生 Error)
const statusCode = err.statusCode
?? err.response?.status
?? err.status;
const errMsg = err.errMsg || err.message || '';
if (statusCode) {
if (statusCode === 404) return { type: 'notFound', statusCode, errMsg, raw: err };
if (statusCode >= 500) return { type: 'server', statusCode, errMsg, raw: err };
if (statusCode === 401 || statusCode === 403) return { type: 'auth', statusCode, errMsg, raw: err };
return { type: 'request', statusCode, errMsg, raw: err };
}
if (/timeout/i.test(errMsg)) {
return { type: 'timeout', errMsg, raw: err };
}
if (/(connect|network|fail)/i.test(errMsg)) {
return { type: 'network', errMsg, raw: err };
}
return { type: 'unknown', errMsg, raw: err };
}
/**
* 根据 classifyHttpError 的结果,映射到 common.http.* 命名空间的 i18n key
*
* 通用网络/接口错误统一走 http.*,调用方通过 $lang(key) 解析文案。
* 原 diy.errTimeout 这类 key 已合并到 http.*,保持项目国际化更专业。
*
* @param {string} type classifyHttpError 返回的 type
* @returns {string|null} 对应的 http.* key;type='business' 时返回 null(透传 raw)
*/
export function httpErrorKey(type) {
switch (type) {
case 'empty': return 'http.networkError';
case 'business': return null; // 透传,不用 key
case 'notFound': return 'http.notFound';
case 'server': return 'http.serverError';
case 'auth': return 'http.auth';
case 'request': return 'http.unknown';
case 'timeout': return 'http.timeout';
case 'network': return 'http.networkError';
case 'unknown':
default: return 'http.networkError';
}
}
export default {
classifyHttpError,
httpErrorKey,
};