我想象使用 bluebirds promisify,你会像这样 promisify bcrypt.compare (你不必使用名称的 Async 部分)
let compareAsync = Promise.promisify(bcrypt.compare);
因为userObject
在第一个 .then 中需要在第二个 .then 中使用,您不能通过返回 compareAsync 来简单地链接 .then,因为这样下一个 .then 将无法访问userObject
一种解决方法是使用一个变量,该变量将在两个 .then 的范围内(但是 ugh)
username = username.toUpperCase();
let text = "SELECT * FROM users WHERE username = $1";
let values = [username];
let uo; //hacky the outer scoped variable
database.one(text, values).then(function (userObject) {
uo = userObject;
return compareAsync(password, userObject.password);
}).then(function(same) {
if (!same) {
throw new Error("Password mismatched!");
}
const serializeObject = {_id: uo._id};
return next(null, serializeObject);
}).catch(function (err) {
return next(err, null);
});
另一个(在我看来更干净)选项是嵌套的 .then
username = username.toUpperCase();
let text = "SELECT * FROM users WHERE username = $1";
let values = [username];
database.one(text, values).then(function (userObject) {
return compareAsync(password, userObject.password)
// [optional] following three lines to generate a "nicer" error for compare failure
.catch(function(err) {
throw "bcrypt.compare failed";
})
// nested .then to pass on the userObject and same at the same time
.then(function (same) {
return { same: same, userObject: userObject };
});
}).then(function (result) {
let same = result.same,
userObject = result.userObject;
if (!same) {
throw new Error("Password mismatched!");
}
let serializeObject = { _id: userObject._id };
return next(null, serializeObject);
}).catch(function (err) {
return next(err, null);
});
注意:bluebird 有一个 promisifyAll 函数......它在对象中承诺函数,并(默认情况下)将Async
后缀添加到函数名称 - 我相信你可以决定不同的后缀名称,但文档会告诉你更多
当承诺单个函数时,您自己声明名称 - 上面可以很容易地
let trumpIsBigly = Promise.promisify(bcrypt.compare);
那么您只需使用trumpIsBigly
代码所在的位置compareAsync
最后一种可能
手卷承诺 compareAsync (主要来自vitally-t的答案,但有补充)
function compareAsync(password1, password2, inValue) {
return new Promise(function (resolve, reject) {
bcrypt.compare(password1, password2, function (err, same) {
err = err || (!same && new Error("Password mismatched!"));
if (err) {
reject(err);
} else {
resolve(inValue);
}
});
});
}
inValue
现在 compareAsync只有在没有错误的情况下才会解析到传入的值,并且也是如此
username = username.toUpperCase();
let text = "SELECT * FROM users WHERE username = $1";
let values = [username];
database.one(text, values).then(function (userObject) {
return compareAsync(password, userObject.password, userObject)
}).then(function (userObject) {
let serializeObject = { _id: userObject._id };
return next(null, serializeObject);
}).catch(function (err) {
return next(err, null);
});
这使得“链”非常简单!