【发布时间】:2015-09-20 16:13:04
【问题描述】:
我正在尝试在数组上运行一些数据库查询(使用sails.js),并在查询返回时执行某些操作。我认为最好的方法是使用 for 循环并异步解决 Promise,一旦它们全部解决,继续。但是,只有我的数组中的最后一个 promise 正在解析,并且它正在解析多次,因为在每个 'User.findOne...' then 函数中,索引是 array.length-1。
我的问题:
- 异步循环中的变量作用域如何工作?解释这一点的最佳资源?
- 解决我的问题的最佳方法是什么?为什么?
- 我应该使用或不使用任何其他模式吗?我对 Promise 和异步 js 还很陌生,所以任何提示都会有所帮助!
我检查过的主要教程
- https://github.com/kriskowal/q
- https://github.com/kriskowal/q/wiki/API-Reference
- https://github.com/bellbind/using-promise-q/
感谢您的帮助!
我的简化代码:
functionWhichReturnsPromise()
.then(function(user){
var promises = [];
Q.try(function(){
for (var index in array) {
var fbid = array[index];// Get fbid from array
promises.push(Q.defer().promise); // Add promise to promise array
// Find userid from fbid; resolve respective promise when finished
User.findOne({facebook_id: fbid}).then(function(userSeen){
promises[index].resolve(userSeen.id);
sails.log('resolved where id=' + userSeen.id); // correct
sails.log('resolved where index=' + index); // PROBLEM: always last index
});
}
}).then(function(){
// For debugging purposes
Q.delay(1000).then(function(){
sails.log(promises[0]); // Unresolved
sails.log(promises[1]); // Unresolved
sails.log(promises[2]); // Only last promise in array is resolved
});
// When the userids have been extracted from above (promises fulfilled)...
Q.all(promises).then(function(seenids){
// Do stuff here (Doesn't get here)
});
});
});
【问题讨论】:
-
是的,您使用的是deferred antipattern。此外,这里没有真正的理由使用
Q.try。 -
@Bergi,我阅读了您关于延迟反模式的参考,但我不太确定如何在没有延迟对象的情况下实现这一点。我有 n 个并行进程要执行,当它们完成后,我需要使用它们的数据。使用 .then 不会对单个承诺起作用,因为我需要等到它们全部完成。我将如何实施呢?我也可以使用 Q() 吗?
-
你没有使用 deferreds 来等待他们完成 - 你使用
Q.all(你应该这样做)。 deferreds 仅用于构造promises中的每一个,并且不需要它们。你应该只做promises.push(Q(User.findOne(…)).then(function(userSeen) { …; return userSeen.id; }))。你甚至可以省略Q()调用,因为findOne()已经返回了一个承诺 -
@Bergi - 谢谢。我想我明白你的意思,但我无法得到一个更简单的版本来工作,我想我错过了一些东西。我发布了一个新问题,因为我意识到它与这个问题有多么相关,所以也许你可以告诉我你的意思;我很乐意接受你的回答。 stackoverflow.com/questions/31551638/…
标签: node.js asynchronous promise sails.js q