【问题标题】:Mongoose Schema Instance Methods is Not a FunctionMongoose 模式实例方法不是函数
【发布时间】: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 } 这个结果回来了,我让用户回来了

标签: node.js express mongoose passport.js


【解决方案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)
    })
  })
})

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

【讨论】:

    猜你喜欢
    • 2021-08-17
    • 1970-01-01
    • 2022-01-22
    • 2015-06-11
    • 2015-09-20
    • 2015-06-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多