随着集合的增长而异步迭代

时间:2015-10-23 16:29:46

标签: javascript angularjs event-loop

我正在迭代一个数组并在该循环中执行一些迭代,这可能会向数组添加一些内容,从而导致循环持续更长时间。 (我知道不应该改变一个迭代的对象,但请耐心等待。)

我正在使用数组作为队列来首先遍历树宽度。

这样可以正常工作,除非每次迭代都是ajax调用,因此是异步的,这意味着在回调队列出列之前循环已经结束了。这意味着当我循环时,我的集合不会增长,并且循环结束时太短。

我的第一直觉是使用闭包来捕获每次迭代的集合,但这无助于这个集合在循环之后错误地开始生长

我的另一个想法是检查像async这样的库是否支持我正在尝试做的事情,但是我不熟悉它并且无法在他们的文档中找到它。

这是我的代码:

for (var i = 0; i < array.length; i++) {
  if (some condition) {
    $http.get(url).success(function (data) {
      array.push(data);  // this happens to late since this function is asynchronous
    });
  }
}

2 个答案:

答案 0 :(得分:0)

您应该使用延迟对象,并且在解决了所有请求之后,将数据附加到数组

var promises = []; 
for (var i = 0; i < array.length; i++) {
  if (some condition) {
    promises.push($http.get(url));
  }
}

$q.all(promises).then(function(data){
   for (var i = 0; i < data.length; i++) {
       array.push(data[i]);
   }
});

详细了解$q here

答案 1 :(得分:0)

我建议承诺:

var all = Promise.all(arr.map(function(x){ //$q.all can also work, see below
   if(condition) { //whatever your condition is
      //can be promises ($http.get() returns a promise) or non-promise values
      return $http.get(); //instead of pushing it
   } else {
      //same as above
      return value; //instead of pushing it
   }
}));
 /* all promise which represents the eventual resolution 
    of all your returned values */

随后你可以自由地做任何你想做的事。

all.then(function(data){
  //data is your array with all your http responses
});

对$ q.all和非承诺值的担忧

看起来$q.all接受一系列承诺;它没有说它将非承诺值转换为已解决的承诺值。如果您计划将$q.all与非承诺值一起使用,那么我建议您明确表示只是为了安全并将非承诺值转换为具有该值的已解决承诺。

$q.resolve(value);