承诺链未按预期顺序执行
Promise chain not executing in expected order
我试图使用一系列promise来验证用户名和密码,但这些promise解决得太早了。
我有两种方法,它们来自两个不同的文件。
首先是我的控制器,它接收请求并调用我的模型进行身份验证。该模型应该返回一个promise,该promise在解析时将具有身份验证结果。
这是我的控制器:
router.post('/api/auth-tokens', function (req, res, next) {
var creds = {user: req.body.user, password: req.body.password};
people.authenticate(creds)
.then(function (result) {
var status = result.valid ? 200: 401;
res.sendStatus(status);
});
});
people
是词法范围的模型。以下是上面使用的方法的当前实现:
var bluebird = require('bluebird');
var bcrypt = require('bcrypt');
var compare = bluebird.promisify(bcrypt.compare);
exports.authenticate = function (args) {
var promise = orm.select({
db: db,
table: table,
where: {id: args.user},
qrm: 'one'
});
promise.catch(function (err) {
var auth_info = { valid: false };
return auth_info;
});
promise.then(function (user) {
var promise = compare(args.password, user.hash)
.then(function (same) {
var auth_info = { valid: same, permissions: user.permissions };
return auth_info;
});
return promise;
});
return promise;
};
orm
返回一个promise,如果用户不存在,它将抛出一个错误;如果找到用户,则解析并生成数据库行。(这就是为什么我有promise.catch
调用。以防用户不存在)
如果用户确实存在,我想调用bcrypt.compare
将输入与数据库行中包含的哈希进行比较。当异步完成时,我想解析promise链并将控制权交还给控制器,返回results
对象。
不过,我遇到的问题是,我的控制器中的.then
正在立即执行,而对orm.select
的调用返回了初始承诺的结果。有人能解释为什么会发生这种情况,以及我该如何解决吗?
之所以会发生这种情况,是因为您已将回调直接连接到orm.select
返回的promise。相反,您需要使用then
返回的promise。
这是promise最大的关键之一:then
返回一个新的promise。(catch
也是。)如果处理程序函数从then
或catch
返回promise(从技术上讲,任何表),则then
(或catch
)返回的新promise将根据您返回的promise进行解析/拒绝。如果处理程序函数返回非promise值,则then
(或catch
)中的新promise将使用该值进行解析(而不是拒绝)。
所以authenticate
可能应该是这样的:
exports.authenticate = function (args) {
return orm.select({
db: db,
table: table,
where: {id: args.user},
qrm: 'one'
})
.then(function (user) {
return compare(args.password, user.hash)
.then(function (same) {
var auth_info = { valid: same, permissions: user.permissions };
return auth_info;
});
})
.catch(function (err) {
var auth_info = { valid: false };
return auth_info;
});
};
请注意,这些更改既是对外部函数的更改,也是对then
中所做的更改。还要注意,无论是来自orm.select
的原始promise被拒绝,还是来自compare
的promise,都将调用catch
回调中的代码。
要了解发生了什么,请将此片段与以下片段进行比较:
// Returning the original promise
// Usually NOT what you want
function foo() {
var promise = new Promise(function(resolve) {
console.log("Starting first promise");
setTimeout(function() {
console.log("Resolving first promise");
resolve("first");
}, 500);
});
promise.then(function() {
promise = new Promise(function(resolve) {
console.log("Starting second promise");
setTimeout(function() {
console.log("Resolving second promise");
resolve("second");
}, 500);
});
});
return promise;
}
foo().then(function(result) {
console.log("Got result: " + result);
});
第二:
// Returning the original promise
// Usually NOT what you want
function foo() {
return new Promise(function(resolve) {
console.log("Starting first promise");
setTimeout(function() {
console.log("Resolving first promise");
resolve("first");
}, 500);
})
.then(function() {
return new Promise(function(resolve) {
console.log("Starting second promise");
setTimeout(function() {
console.log("Resolving second promise");
resolve("second");
}, 500);
});
});
}
foo().then(function(result) {
console.log("Got result: " + result);
});
您的控制器执行的承诺与使用bcrypt.compare 的控制器不同
这样做是为了确保people.authenticate返回一个承诺链,该承诺链解析为比较后的内部结果:
var promise = orm.select(/* ... */)
.then(/* bcrypt usage here */)
.catch(/* error handling here */);
return promise;
- 使用appendChild()动态添加的脚本是按顺序执行还是并行执行
- 如何在angularjs中按顺序执行多数据ng应用程序
- 要按顺序执行的异步代码
- AngularJS:如何按照预定义的顺序执行函数
- 按顺序执行导入的 Javascript 函数
- 无法让 jQuery 以正确的顺序执行代码
- 触发后的 Javascript 顺序执行
- $http.post() angularjs 响应函数未按正确的顺序执行
- 如何按顺序执行 jQuery 函数
- 为什么Javascript不按顺序执行代码
- 对象在循环中运行时未定义,但在按顺序执行时未定义
- 按顺序执行ajax请求的动态编号
- javascript在网络上的顺序执行
- SQL语句是通过PhoneGap'按顺序执行的吗;的Web SQL数据库
- jQuery Deferred和Promise用于同步和异步函数的顺序执行
- 顺序执行js
- 如何按顺序执行承诺数组
- 有没有更好的方法以一定的顺序执行一堆部分异步的jQuery函数
- 如何确保 Dojo 模块按特定顺序执行
- 为什么我的 JavaScript 不能按顺序执行