node mongoose methods 怎么在调用的时候拿不到该方法

已注销
  • 883

在做一个用户注册&登陆的功能,在创建用户的时候使用了bcrypt加密密码,在登陆的时候需要解密然后对密码进行对比,密码相同则登陆成功

// 版本信息如下
node:v10.13.0 (LTS)
"mongoose": "^5.4.11"
"bcrypt": "^3.0.4"
"koa": "^2.7.0"
// Schema相关代码
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const Schema = mongoose.Schema;
const newSchema = new Schema({
    ...
})
newSchema.pre('save', function (next) {
    // 此处在存储密码前做了加密操作,当注册用户后,数据库看的是加密后的用户密码
})

newSchema.methods.comparePassword = function(candidatePassword, cb) {
    bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
    if (err) {
      return cb(err);
    }
    cb(null, isMatch);
  });
})
module.exports = mongoose.model("User", newSchema);
// 接口部分代码如下
const user = require('../controller/user'); // 导入上面的Schema相关代码
router.post('/login', async (ctx, next) => {
    let results = await user.find({email: ctx.request.body.email}, (err, res) => {
      return res
    }); // 根据邮箱先找到该用户
    
    user.comparePassword(ctx.request.body.password, (err, isMatch) => { // 此处报错user.comparePassword is not a function
        if (err) {
          // throw err
          console.log('错误')
        }
        console.log('结果', isMatch)
      });
})

以上代码我基本是照这网上的demo 链接搬来的,但是却一直在报错

// 如若我在使用的Schema的时候使用如下代码
let userMsg = new user({
    email: ctx.request.body.email,
    password: ctx.request.body.password
  });
// 那么我userMsg.comparePassword就是可以正常调用到的,但是在Schema模块密码使用获取的不对

newSchema.methods.comparePassword = function(candidatePassword, cb) {
  console.log('aaa', this);
    // 此处的this 就是ctx.request.body.email和ctx.request.body.password的值,会导致密码验证一直失败
  bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
    if (err) {
      return cb(err);
    }
    cb(null, isMatch);
  });
};

请问一下,这是怎么回事,可以的话,也希望可以说下methods和methods的区别,感觉网上大多的说的都看不太明白,最好可以用简单的语言描述

mongodb的官网也有一个demo 链接,代码都基本一致

回复
阅读 637
1 个回答

你的第三个代码块里写的是user.comparePassword(...),这里的user是你在第二个代码块里导出的mongoose.model,问题就在这了。方法是需要添加给schema而不是model,具体如下:

下面是方法定义:

newSchema.methods.comparePassword_thisIsDoc = function(cb) {
    // 这里的this指代的是`Document`对象
}
newSchema.statics.comparePassword_thisIsModel = function(pwd, cb) {
    // 这里的this指代的是`Model`对象
}

下面是具体使用:

user.find({email: ctx.request.body.email}, (err, res) => {
    const doc = res[0];
    if(doc!==null) {
        // 下面是使用查询到的document判断
        doc.comparePassword_thisIsDoc(cb)
        // 下面是使用model判断
        // user.comparePassword_thisIsModel(pwd, cb);
    }
      return res
}); 

PS: 你上述写的let results = await user.find(...)是无效的写法,正确应该这么写:

// 同步式写法
let results = await user.find(...).exec();
// 回调式写法 [err总位于参数第一位]
user.find(..., function(err, docs) {
    
})
你知道吗?

宣传栏