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
相关产品推荐
相关产品推荐

