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

Mongoose数据保存前验证报错:done is not a function

解决Mongoose验证器中"done is not a function"错误

这个done is not a function错误大概率是Mongoose版本差异导致的异步验证器API使用不当,我来帮你拆解问题并解决:

情况1:你使用的是Mongoose 4.x版本

在Mongoose 4.x中,异步验证器必须显式声明isAsync: true,否则Mongoose会把它当成同步验证器,不会传递done参数——这就是为什么done是undefined,调用它时报错。

修复后的代码:

userSchema.path('email_id').validate({
  validator: function(value, done) {
    this.model('User').count({ email_id: value }, function(err, count) {
      if (err) {
        return done(err);
      }
      // count>0时返回false(验证失败),否则返回true(验证通过)
      done(!count);
    });
  },
  message: 'Email already exists',
  isAsync: true // 必须添加这个选项
});

情况2:你使用的是Mongoose 5.x及以上版本

Mongoose 5+已经简化了异步验证器的写法,更推荐用Promise/async-await替代回调,同时注意count()方法在Mongoose 6.x已经被弃用,官方推荐用countDocuments():

修复后的代码(更简洁,也避免了回调问题):

userSchema.path('email_id').validate(async function(value) {
  // 查询数据库中该邮箱的数量,排除当前文档(避免更新自己时误判)
  const query = { email_id: value };
  if (this._id) {
    query._id = { $ne: this._id };
  }
  
  const count = await this.model('User').countDocuments(query);
  // 返回true表示验证通过(邮箱未存在),false表示验证失败(邮箱已存在)
  return count === 0;
}, 'Email already exists');

额外提示

为什么要排除当前文档?因为当用户更新个人资料时,如果没有修改邮箱,这时候查询到的count会包含自己的记录,导致验证失败。加上_id: { $ne: this._id }就能避免这个问题,让验证逻辑更严谨。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:15:24