使用express-validator做校验时异步SQL查询逻辑被跳过怎么办?
问题背景
需要在用户提交数据前校验输入的分类是否真实存在,使用express-validator做字段校验时,.exists()、.trim()等常规校验规则运行正常,但自定义.custom异步校验逻辑仅在中间件中生效,普通函数中无法生效。
原自定义校验代码如下:
.custom(value => { return new Promise((resolve, reject) => { connection.query("SELECT id FROM cat WHERE cat_name = ?", [value], (err, results) => { if (err) reject(err); if (results[0] == 'undefined') reject(new Error('This topic does not exist or is misspelled.')) resolve(); }) }); })
核心问题原因
- 自定义校验返回Promise属于异步逻辑,express-validator的异步校验必须等待Promise执行完成才能拿到结果。普通同步函数中直接调用时,未等待异步逻辑执行完毕就提前返回,因此校验不会生效。
- 原代码存在逻辑漏洞:
results[0] == 'undefined'是判断值等于字符串'undefined',而分类不存在时SQL返回的是空数组,results[0]为原始值undefined,该判断条件永远不会触发,即使分类不存在也不会抛出校验错误。
修复方案
- 先修正自定义校验的判断逻辑:
.custom(value => { return new Promise((resolve, reject) => { connection.query("SELECT id FROM cat WHERE cat_name = ?", [value], (err, results) => { if (err) return reject(err); // 分类不存在时返回的结果为空数组,直接判断数组长度即可 if (!results || results.length === 0) { return reject(new Error('分类不存在或拼写错误')) } resolve(); }) }); })
- 普通函数中调用校验逻辑时,必须用
async/await等待异步校验执行完成,示例写法如下:
const { body, validationResult } = require('express-validator'); // 封装为可复用的校验函数 const checkCatExists = async (inputCatName) => { // 构造校验规则 const validateRules = [ body('catName') .exists().withMessage('分类名称不能为空') .trim() .custom(value => { return new Promise((resolve, reject) => { connection.query("SELECT id FROM cat WHERE cat_name = ?", [value], (err, results) => { if (err) return reject(err); if (!results || results.length === 0) { return reject(new Error('分类不存在或拼写错误')) } resolve(); }) }); }) ]; // 手动触发所有校验规则执行,等待异步完成 await Promise.all(validateRules.map(rule => rule.run({ body: { catName: inputCatName } }))); // 收集校验结果 const errors = validationResult({ body: { catName: inputCatName } }); return errors.isEmpty() ? { pass: true } : { pass: false, errors: errors.array() }; }; // 调用时必须加await等待结果 const validateResult = await checkCatExists('测试分类名');
补充说明
express-validator原生设计为Express中间件使用,路由层直接插入校验中间件、路由处理函数中调用validationResult获取结果是官方推荐的最优使用方式,非中间件场景使用需要手动处理异步逻辑,成本更高。
内容的提问来源于stack exchange,提问作者Nik
相关产品推荐
相关产品推荐

