我有一个带有mongoDB的Node.js API。有一条创建用户并需要哈希密码的路由,为此我使用了bcryptjs包。
路线如下:
router.route('/user')
.post(function(req, res) {
if(req.body.password === req.body.passwordConfirm) {
userManager.addUser(req.body)
.then(function(response) { // waiting for the result of the mongoDB save
res.send({data:response});
});
} else {
res.send({err:'passwords do not match'});
}
})
和userManager.addUSer:
this.addUser = function(userobject) {
bcrypt.genSalt(10, function(err, salt) { // generate a salt
if(err !== null) {
console.log(err);
} else {
bcrypt.hash(userobject.password_hash, salt, function(err, hash) { // hash pw
if(err !== null) {
console.log(err);
else {
userobject.password_hash = hash; // store hash in user obj
var user = new User(userobject);
return user.save().catch(function(err){ // save user in mongoDB
console.log(err);
});
}
});
}
});
};
我收到错误消息:"无法读取属性'然后' of undefined",它告诉我,我没有收到addUser的承诺。我看起来和bcryptjs遗憾地不使用承诺,但是,mongoose确实如此。 (补充一点:
var mongoose = require('mongoose').Promise = Promise;
没有帮助)
我尝试用拒绝和解决方法将函数包装在一个promise中,但是这会给出这个错误:" TypeError:Promise resolver undefined不是函数"。
我如何得到mongoose的save()函数返回到post route中的.then()的承诺?我尝试在两个bcrypt函数前面添加return但是那个也没有...
欢迎任何建议!
答案 0 :(得分:1)
您的addUser
函数会向其调用方返回承诺。您正在使用return
回调函数执行bcrypt.hash
,但这与addUser
的返回值无关。
看起来addUser
必须使用一些非启用Promise的API,因此您仍然坚持使用new Promise
,类似这样的内容(请参阅***
条评论) :
this.addUser = function(userobject) {
return new Promise(function(resolve, reject) { // ***
bcrypt.genSalt(10, function(err, salt) { // generate a salt
if(err !== null) {
reject(err); // ***
} else {
bcrypt.hash(userobject.password_hash, salt, function(err, hash) { // hash pw
if(err !== null) {
reject(err); // ***
else {
userobject.password_hash = hash; // store hash in user obj
var user = new User(userobject);
resolve(user.save()); // *** save user in mongoDB
}
});
}
});
});
};
另请注意,我没有addUser
只是吞咽错误;相反,它们会传播给呼叫者。调用者应该处理它们(即使"处理"只是记录)。
答案 1 :(得分:1)
您不会从this.addUser
返回承诺,您必须将基于bcrypt
的回复转换为承诺。您可以转换整个bcrypt
API以支持基于Promise的功能,例如使用蓝鸟图书馆的promisifyAll
,或者像{1}}一样手动执行:
new Promise
或那样:
this.addUser = function(userobject) {
return new Promise((resolve, reject) => {
bcrypt.genSalt(10, (err, salt) => {
if (err) {
reject(err);
} else {
bcrypt.hash(userobject.password_hash, salt, function(err, hash) {
if (err) {
reject(err)
} else {
resolve(hash)
}
})
}
});
})
.then(hash => {
userobject.password_hash = hash; // store hash in user obj
var user = new User(userobject);
return user.save() // save user in mongoDB
})
.catch(function(err) {
console.log(err);
});
}
答案 2 :(得分:0)
在对bcryptjs的更改日志中进行了一些挖掘后,我发现他们添加了promises但没有更新文档..如果省略回调,genSalt en哈希方法将返回一个promise。这将转化为:
this.addUser = function(userobject) {
return bcrypt.genSalt(10).then((salt) => {
return bcrypt.hash(userobject.password, salt).then((hash) => {
userobject.password_hash = hash;
var user = new User(userobject);
return user.save();
});
});
};