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

使用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,该判断条件永远不会触发,即使分类不存在也不会抛出校验错误。
修复方案
  1. 先修正自定义校验的判断逻辑:
.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();
    })
  });
})
  1. 普通函数中调用校验逻辑时,必须用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 10:39:00