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 Save 方法的Sinon Mock(带有承诺)