You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

express validator中service/data层异常处理方案咨询

架构调整方案
  • 首先改造自定义校验逻辑,区分校验失败和系统异常
    不要把校验过程中所有抛出的错误都默认归为参数校验错误。你可以在调用repo的自定义校验函数中加异常捕获逻辑:如果是预期内的业务校验失败(比如校验的资源不存在、参数值不符合业务规则),再抛出校验错误;如果是DB连接断开这类非预期的系统异常,直接把错误传递到全局错误中间件,不进入express validator的默认校验错误收集流程。

示例代码:

// 原校验逻辑
body('targetId')
  .custom(async (val) => {
    const exist = await targetRepo.checkExists(val)
    if (!exist) throw new Error()
  })
  .withMessage('目标资源不存在')

// 改造后校验逻辑
body('targetId')
  .custom(async (val, { req }) => {
    try {
      const exist = await targetRepo.checkExists(val)
      if (!exist) throw new Error('VALIDATION_ERROR:目标资源不存在')
      return true
    } catch (err) {
      // 仅业务校验失败走校验错误逻辑
      if (err.message.startsWith('VALIDATION_ERROR:')) {
        err.message = err.message.slice(17)
        throw err
      }
      // 系统异常挂载到req上,后续单独处理
      req.unexpectedError = err
      return false
    }
  })
  .withMessage('目标资源不存在')
  • 新增统一校验结果处理中间件
    在校验链和控制器之间新增一层中间件,优先处理校验过程中捕获的系统异常,再处理常规校验错误:
const validate = (req, res, next) => {
  // 优先处理系统异常,直接走全局错误中间件
  if (req.unexpectedError) return next(req.unexpectedError)
  // 处理常规参数校验错误
  const errors = require('express-validator').validationResult(req)
  if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() })
  }
  next()
}
  • 全局错误中间件不需要做任何改造
    你原来的全局错误中间件已经负责统一打日志、返回响应,所有系统异常不管是从控制器冒泡上来还是从校验中间件传递过来,都会走到同一套处理逻辑,不需要在service、repo层新增任何日志代码,也不会再把DB连接异常这类500错误误判为400参数错误。

内容的提问来源于stack exchange,提问作者Lars Ahman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 06:00:02