asynchronousNode.js循环中的variables范围

我想在数组上运行一些数据库查询(使用sails.js),并在查询返回时,做一些事情。 我认为最好的方法是使用for循环,并解决承诺asynchronous,一旦他们都解决了,继续下去。 然而,只有我的数组中的最后一个承诺是解决,它是解决了多次,因为在每个“User.findOne …”然后函数,索引是array.length-1。

我的问题:

  1. asynchronous循环中的variables作用域如何工作? 最好的资源来解释这个?
  2. 什么是解决我的问题的最好方法? 为什么?
  3. 还有其他的模式,我应该使用或不使用? 我对承诺和asynchronousJS相当陌生,所以任何提示都会有帮助!

主要教程我已经检查

  • 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) }); }); }); 

在Javascript中,variables的作用域是函数而不是大括号。

因此,在下面的代码中, var index的范围不是for循环的大括号,范围实际上是for循环所在的函数。

 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 }); } }) 

在for循环中,你调用asynchronous函数,在你的情况下它的mongodb调用( findOne )。 您应该始终假定这些asynchronous函数可以运行任意毫秒数(取决于函数)。 但通常情况下,通常循环会在asynchronous函数运行之前完成。 即使在这些函数开始运行之前,for循环也会触发所有这些asynchronous函数。 问题是所有那些待定的asynchronous函数仍然指向那个variablesindex 。 而且这个variables对所有这些variables都是通用的,因为index在外部函数的范围之内。

这是由于Javascript中的闭包而产生的一个问题。 而为了解决这个问题,我们需要使用更多的closures。

关于你可以谷歌closures的主题有很多资源。 但是要通过MDN的描述 。

如果你捕捉循环内的另一个函数的index值,那么你将会很好。

这是我的build议解决您的问题。 我还没有testing过,但你明白了。

 Q.try (function () { array.forEach( function(ele, idx, array) { (function(index) { 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 }); })(idx); }) }) 

希望这可以帮助。

另请注意: 使用for …来迭代数组是不正确的 。