Mongoose 模式实例方法不是函数

Posted

技术标签:

【中文标题】Mongoose 模式实例方法不是函数【英文标题】:Mongoose Schema Instance Methods is Not a Function 【发布时间】:2019-10-27 07:46:31 【问题描述】:

我以前有一个工作版本的 mongoose 实例方法。我不确定这次对它有何不同。这次我唯一不同的是,我将server.js文件之外的mongoose连接函数分离成一个配置文件,该文件将被导入并调用connect()函数。

我将主要在护照中使用此实例方法和本地策略来登录用户。当我在之前的UserModel.findOne( email ) 找到的用户实例上调用我的实例方法时,verify(password) 实例方法不会被调用,也不会引发任何错误。

出于测试目的,我尝试将UserModel.findOne() 硬编码到连接字段中,并且确实让用户回来了。然后我决定从返回的名为 verify() 的用户实例中调用我的实例方法。

我还尝试将方法的名称更改为comparePassword,我尝试使用静态测试来检查它是否被调用(它没有被调用),我还尝试研究其他导入我的架构和模型的方法,似乎没有工作。我已经尝试了异步/等待尚未改变输出


文件:mongo.db.js

const connect = () => 
  return new Promise((resolve, reject) => 
    mongoose.connect(
      config.get('DB.STRING'),
       useCreateIndex: true, useNewUrlParser: true ,
      async (err) => 
        if (err) reject(err)
        resolve()
        // TESTING INSTANCE METHODS
        await mongoose.connection
          .collection('users')
          // HARD CODED TEST EMAIL
          .findOne( email: 'braden_feeney@hotmail.com' , (err, result) => 
            if (err) reject(err)
            console.log(result)
            console.log(result.verify('test1234'))
          )
      ,
    )
  )


const close = () => 
  return mongoose.disconnect()


export default  connect, close 

文件:passport.config.js

passport.use(
  new LocalStrategy(
    
      usernameField: 'email',
      passwordField: 'password',
    ,
    async (email, password, done) => 
      try 
        // Find the user given the email
        const user = await User.findOne( email )
        // If not found
        if (!user) return done(null, false)
        // Check if the password is correct
        const isValididated = await user.verify(password)
        // If not matched
        if (!isValididated) return done(null, false)

        // Return the user
        done(null, user)
       catch (error) 
        done(error, false)
      
    ,
  ),
)

文件:users.model.js

const UserSchema = new Schema(
  // HIDDEN FOR SECURITY
   ... ,
   versionKey: false, timestamps: true ,
)

// HIDDEN FOR SECURITY - PRE SAVE WORKS AS EXPECTED
UserSchema.pre('save', async function(next)  ... )

// THIS IS THE METHOD THAT SHOWS AS 'Not a Function'
UserSchema.methods.verify = function(password) 
  bcrypt.compare(password, this.password, (err, res) => 
    if (err) return new Error(err)
    return res
  )


export default model('User', UserSchema)

当我调用 user.verify(password) 时,我希望看到函数返回一个布尔值。

实际结果是抛出陈述的错误 TypeError: user.verify is not a function

【问题讨论】:

你能在console.log(user) 后面看到await User.findOne( email ) 的样子吗? @Akrion _id: 5d010bb74b129397607e2abb, _workspaceID: 5d003c0c34aea526f8c44b65, firstName: 'Arlie', lastName: 'Veum', email: 'braden_feeney@hotmail.com', password: '...', createdAt : 2019-06-12T14:27:03.210Z, updatedAt: 2019-06-12T14:27:03.210Z 这个结果回来了,我让用户回来了 【参考方案1】:

这部分没有意义:

async (email, password, done) => 
    try 
        const user = await User.findOne( email )
        if (user) // <-- if you have a user record
          return done(null, false) // <-- you return!
        // There was no valid user ... how would there be user.verify?
        const isValididated = await user.verify(password)
        if (!isValididated) return done(null, false)
          done(null, user)
     catch (error) 
        done(error, false)
    

您似乎返回了有效用户,但当您没有用户时调用user.verify。所以看来你的流程有点问题。

【讨论】:

是的,你没看错,它应该是if (!user) return done(null, false)。这将在以后以任何一种方式被捕获,但我仍然收到实例方法的问题。 是的,当它到达user.verify(password) 部分时我仍然收到错误【参考方案2】:

在修改了 mongoose 如何创建实例方法之后,我尝试使用另一种方法来使该方法工作。我不得不将bcrypt.compare() 包装在一个承诺中,因为我的代码没有等待响应。

文件:users.model.js

UserSchema.method('verify', function(password) 
  return new Promise((resolve, reject) => 
    bcrypt.compare(password, this.password, (err, res) => 
      if (err) reject(err)
      resolve(res)
    )
  )
)

我仍然更喜欢我的问题中提到的方式,因为我相信它看起来更干净并且不依赖字符串作为方法名称。

【讨论】:

以上是关于Mongoose 模式实例方法不是函数的主要内容,如果未能解决你的问题,请参考以下文章

Mongoose“静态”方法与“实例”方法

未来所有模型实例的 Mongoose Save 方法的Sinon Mock(带有承诺)

Mongoose 模型中的自定义实例或静态方法中的验证错误

Typescript & Mongoose - "this" 在实例方法中不可用

Nest.js 为模型创建静态和实例函数的方法是啥?

一天一个设计模式——Prototype 原型模式