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
相关产品推荐
相关产品推荐

