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

Custom Validators中Promise.reject()与throw new Error()的使用区别

结论先行

你给出的两个示例在执行效果上完全等价:Promise.then 回调内同步抛出的 Error 会自动被外层 Promise 包装为 rejected 状态返回,express-validator 底层拿到的校验结果没有任何差异。


二者的核心区别与适用场景

  • 必须使用 Promise.reject() 的场景:
    当你的错误抛出逻辑不在 Promise 链的同步回调内时(比如老式回调 API、setTimeout 等非 Promise 异步回调),throw 出来的错误无法被外层 Promise 捕获,只会导致进程抛出未捕获异常,这时候必须通过 Promise.reject() 主动返回拒绝状态。
    示例:
    body('phone').custom(value => {
      return new Promise((resolve, reject) => {
        // 基于回调的老式接口
        legacyCheckPhoneExist(value, (err, isExist) => {
          if (err) return reject('手机号校验失败')
          if (isExist) return reject('手机号已注册')
          resolve()
        })
      })
    })
    
  • 二者都可用的场景差异:
    仅语义层面有区别:throw new Error() 更偏向同步逻辑的异常抛出写法,Promise.reject() 更明确表达这是异步校验流程的预期错误返回。

选型建议

二者都可用的场景下没有强制优劣,按团队编码规范和个人习惯选择即可:

  • 如果使用 async/await 写法写自定义校验,throw new Error() 写法更自然简洁,是大部分人的首选:
    body('email').custom(async value => {
      const user = await User.findUserByEmail(value)
      if (user) throw new Error('E-mail already in use')
    })
    
  • 如果想要明确区分「校验不通过的预期错误」和「代码运行异常」,可以优先选 Promise.reject(),语义更清晰。
  • 注意无论选哪种写法,都建议传递 Error 对象而非纯字符串,方便后续排查问题时能拿到错误堆栈信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 08:12:05