--- kind: error_handling name: 后端统一响应与前端拦截器式错误处理 category: error_handling scope: - '**' source_files: - backend/src/utils/response.js - backend/src/middleware/auth.js - backend/src/app.js - backend/src/config/redis.js - frontend/src/utils/request.js --- ## 1. 采用的体系与模式 - 后端:Express + Sequelize,**无全局错误中间件**。每个路由 handler 使用 `try/catch` 包裹业务逻辑,捕获异常后通过 `logger.error` 记录日志,再以统一的 `ApiResponse.error()` 返回 `{ code, msg, data }` 结构。 - 前端(frontend):基于 axios 的**请求/响应拦截器**集中处理 HTTP 状态码与业务码 `code === 0` 的错误,自动弹出 ElMessage、401 时清除本地 token 并跳转登录页。 - 前端(frontend_v2):采用 alova + Naive UI 的独立实现,错误处理策略与 frontend 类似但组件库不同。 - 未使用自定义 Error 类、未定义业务错误码枚举,也未使用 `throw new CustomError(...)` 这类结构化错误对象;错误信息以字符串形式在路由层直接构造。 ## 2. 关键文件与位置 - 后端统一响应封装:`backend/src/utils/response.js` - 认证中间件(401/403 错误入口):`backend/src/middleware/auth.js` - 应用启动与数据库同步异常兜底:`backend/src/app.js` - Redis 连接错误监听:`backend/src/config/redis.js` - 前端请求封装与拦截器:`frontend/src/utils/request.js` - 各业务路由(大量 try/catch + ApiResponse.error 示例):`backend/src/routes/*.js`(auth.js、blacklist.js、brands.js 等) ## 3. 架构与约定 - **统一响应体**:所有成功/失败接口均返回 `{ code: 1|0|2, msg, data }`。`code=1` 成功,`code=0` 业务错误,`code=2` 无数据。调用方可据此判断是否继续。 - **HTTP 状态码约定**:认证失败返回 401,权限不足返回 403,其余业务错误默认 200 + `code=0`。未对 5xx 做全局兜底,依赖 Node 默认行为或路由内 catch。 - **错误传播路径**:路由层 → `ApiResponse.error(msg)` → 前端响应拦截器 → `ElMessage.error(res.msg)` 或直接 reject Promise,由业务组件自行处理。 - **鉴权错误**:`authMiddleware` 区分 TokenExpiredError 与普通解析错误,分别返回“登录已过期”和“无效凭证”,前端据此提示并跳转。 - **可跳过全局提示**:前端支持在请求配置中设置 `skipErrorToast: true`,让上层组件自行控制错误提示(如推送进度弹窗场景)。 ## 4. 开发者应遵循的规则 - 新增路由一律用 `try/catch` 包裹核心逻辑,catch 中先 `logger.error(e.message)`,再 `res.json(ApiResponse.error('中文错误描述'))`。 - 不要直接 `throw` 自定义错误对象到上层;当前代码库没有全局错误处理器来消费它。 - 需要返回 HTTP 401/403 的场景(如鉴权、权限校验)优先使用 `authMiddleware` 及 `requireSuperAdmin`,避免在各路由重复实现。 - 前端发起请求时,如需自行展示错误(例如表单提交),可在 axios 配置中添加 `skipErrorToast: true`,并在 `.catch` 中手动 `ElMessage.warning/error`。 - 对于网络超时、DNS 解析失败等底层错误,前端拦截器会统一提示“网络错误”,业务层无需重复处理。 - 若需引入更精细的错误分类(如参数校验失败 vs 数据库不可用),建议先在 `utils/response.js` 中扩展 `ApiResponse` 方法或在 `validators/` 中集中抛出带 code 的错误对象,再由路由层统一转换,以保持前后端一致。