如何修改Express.js自定义验证中间件以支持验证规则链式调用
实现思路
原来的代码无法支持链式调用的核心原因是:每个验证方法(minLength、maxLength)直接返回了Express中间件函数,导致后续无法继续调用同实例的其他方法。要实现链式调用需要调整为以下逻辑:
- 每个验证方法执行后返回当前
Body实例本身,支持后续链式调用其他验证方法 - 内部维护一个验证规则队列,所有链式添加的规则都会存入这个队列
- 最终将整个
Body实例包装为标准Express中间件,执行时依次运行队列中所有验证规则
修改后的完整代码
validator.js 调整后代码
/* validator.js */ const createBodyInstance = (check_this) => new Body(check_this) const Body = function(check_this) { // 内部存储所有验证规则 this.validationQueue = [] this.minLength = (length) => { // 把验证规则推入队列 this.validationQueue.push((req, res, next) => { if(req.body[check_this] && req.body[check_this].length < length) { // 此处可自定义验证失败逻辑,比如返回错误响应 return res.status(400).json({ error: `${check_this}长度不能小于${length}位` }) } next() }) // 返回当前实例,支持链式调用 return this } this.maxLength = (length) => { this.validationQueue.push((req, res, next) => { if(req.body[check_this] && req.body[check_this].length > length) { return res.status(400).json({ error: `${check_this}长度不能大于${length}位` }) } next() }) return this } // 执行所有验证规则的核心方法 this.runValidations = (req, res, next) => { let currentIndex = 0 const runNextValidation = () => { if(currentIndex >= this.validationQueue.length) return next() this.validationQueue[currentIndex++](req, res, runNextValidation) } runNextValidation() } } // 导出包装后的body方法,让实例可以直接作为中间件被Express调用 module.exports = { body: (...args) => { const instance = createBodyInstance(...args) return (req, res, next) => instance.runValidations(req, res, next) } }
router.js 调用方式(和你期望的完全一致)
/* router.js */ const { body } = require("./validator") router.post("/change-password", [ body("password").minLength(6).maxLength(8) ], function(req, res) { /* other code */ })
扩展说明
如果需要新增其他验证规则(比如邮箱格式验证、数字范围验证),只需要按照minLength的写法:往validationQueue推入对应的验证逻辑,然后返回this即可,不需要调整整体结构。
内容的提问来源于stack exchange,提问作者May Myat Thuzar
相关产品推荐
相关产品推荐

