我是一个尝试理解node.js的初学者。我尝试在我的护照本地策略中将回调转换为promise,转换为promise后,尝试登录时遇到错误,提示“未定义用户”。我确定在转换回调函数时我做错了什么,请您看看我的代码并向我解释我做错了什么地方。
这是上一个回调
exports.newLocalStrategy= new localStrategy(
(username,password,done)=>{
User.find({username: username},(err, user)=>{
if (err) throw err;
if(user.length == 0){
console.log("Unknown User");
return done(null,false,{message: 'unknown User'});
}
comparePassword(password,user[0].password, (err,isMatch)=>{
if (err) throw err;
if (isMatch){
return done(null, user);
return res.send("Loggedin");
}else{
console.log('invalid password');
return done(null, false, {message:"Invalid password"});
}
})
});
});
const comparePassword = (candidatePassword, hash, callback)=>{
bcrypt.compare(candidatePassword, hash, (err, isMatch)=>{
if (err) return callback(err);
callback(null, isMatch);
});
}
和我承诺的代码:
exports.newLocalStrategy= new localStrategy(
(username,password,done)=>{
//promise
User.find({username: username})
.then(user =>{
if(user.length ==0){
return done(null, false,{message: 'unknown user'})
}
})
.catch(err => {return done(null,err)})
comparePassword(password,user[0].password)
.then(isMatch => {
if (isMatch) return (done,null);
})
.catch(err=>{return done(null,err)})
});
const comparePassword = (candidatePassword, hash, callback)=>{
return new Promise((resolve,reject)=>{
bcrypt.compare(candidatePassword, hash, (err, isMatch)=>{
if (err) return reject(err);
resolve(null, isMatch);
});
})
}
我在comparePassword(password,user[0].password)
这行出现错误
答案 0 :(得分:1)
这里有两个主要问题。既然您似乎想继续让newLocalStrategy
接受done
回调,我假设您不希望它返回承诺,而只是在内部使用承诺。
exports.newLocalStrategy = new localStrategy(
(username, password, done) => {
User.find({
username: username
})
.then(user => {
if (user.length == 0) {
return done(null, false, { message: 'unknown user' })
}
})
.catch(err => {
return done(null, err)
})
// this is in the wrong scope, `user` is not defined here
comparePassword(password, user[0].password)
.then(isMatch => {
if (isMatch) return (done, null);
})
.catch(err => {
return done(null, err)
})
});
const comparePassword = (candidatePassword, hash, callback) => {
return new Promise((resolve, reject) => {
bcrypt.compare(candidatePassword, hash, (err, isMatch) => {
if (err) return reject(err);
// resolve takes only one parameter
resolve(null, isMatch);
});
})
}
进行更正后,它应如下所示:
exports.newLocalStrategy = new localStrategy((username, password, done) => {
User.find({ username }).then(users => {
if (users.length === 0) {
throw new Error('unknown user');
} else {
return Promise.all([users, comparePassword(password, users[0].password)]);
}
}).then(([users, isMatch]) => {
if (isMatch) done(null, users);
else throw new Error('invalid password');
}).catch(err => {
done(null, false, err)
});
});
const comparePassword = (candidatePassword, hash) => {
return new Promise((resolve, reject) => {
bcrypt.compare(candidatePassword, hash, (err, isMatch) => {
if (err) reject(err);
else resolve(isMatch);
});
});
};
最令人困惑的部分可能是一行
return Promise.all([users, comparePassword(password, users[0].password)]);
这本可以简化为
return comparePassword(password, users[0].password);
如果不必将users
传递到下一个.then()
,因为如果有匹配项,它将被传递到done()
。 Promise.all()
接受一个承诺数组并在调用下一个.then()
回调之前解析它们。 users
不是一个承诺,但会在内部使用Promise.resolve()
隐式转换为一个承诺,并与从comparePassword()
解析的值一起传递。
为将来参考,您可以使用util.promisify()
来定义comparePassword()
:
const comparePassword = require('util').promisify(bcrypt.compare);