2014-04-03 43 views
9

我正在通过angular.forEach循环数组并调用非角度ajax库(Trello client.js)。客户端确实有'成功'和'错误'回调,但不返回角延迟。我想在所有ajax调用完成后执行一个函数。AngularJS等待foreach内部的所有异步调用

我有以下代码:

$scope.addCards = function(listId) 
      { 
       var cardTitles = $scope.quickEntryCards[listId].split('\n'); 
       angular.forEach(cardTitles, function(cardTitle,key) 
       { 
        Trello.post('/cards', { 
         name:cardTitle, 
         idList:listId 
        },function(){ }, function(){ }); 
       }); 
       //TODO: wait for above to complete... 
       $scope.init($routeParams.boardId); 
       $scope.quickEntryCards[listId] = '';  
      }; 

我可以在那// TODO并在回调函数,使最后两行只有在所有帖子后运行成功或失败怎么办?

回答

24

使用角度$ q服务的伪代码。

requests = []; 

forEach cardTitle 
    var deferred = $q.defer(); 
    requests.push(deferred); 
    Trello.post('/path', {}, deferred.resolve, deferred.reject); 

$q.all(requests).then(function(){ 
    // TODO 
}); 
+0

我认为这让我朝着正确的方向发展,但Trello.post并没有兑现承诺。所以我需要钩入他们使用的回调和角度承诺... – Daniel

+1

有趣的是,我看到我错过了你的问题。奇怪,因为它看起来会返回一个承诺。您可以使用$ q.defer()来做出任何承诺。我将添加伪代码为例。 –

+0

是的,这是做到了。 Trello的API是异步的,只是没有角度的承诺,所以它很好地填充(现在我看到了如何去做);只需将deferred.resolve和deferred.reject作为Trello的成功和回调方法直接传递就可以缩短一点,如下所示: Trello.post( '/路径',{},deferred.resolve,deferred.reject); – Daniel

3

看看异步库https://github.com/caolan/async

因此,您可以并行或串联运行所有异步函数,并且一旦完成所有asyn函数,就会执行常用的回调。

async.parallel([ 
    function(){ ... }, 
    function(){ ... } 
], callback); 

async.series([ 
    function(){ ... }, 
    function(){ ... } 
]); 

希望它有帮助。

+0

岂不异步的'forEach' /'forEachSeries'更合适? –

2

简单地说,你可以这样做

var jsonArray3=[]; 
angular.forEach($scope.jsonArray1,function(value,key){ 
    angular.forEach(jsonArray2,function(v,k){ 
     if(v.id==value.id){ 
      $scope.jsonArray3.push(v); 
     } 
    }) 
}) 



$q.all($scope.jsonArray3).then(function(data){ 
    console.log("data:",data); 
}) 
10

对于那些寻找问题的答案的标题“AngularJS等待的foreach完成内部的所有异步调用”,这里是一个通用的方法实现这一目标,还采用了棱角分明的$ q服务:

$scope.myArray = [1, 2, 3, 4, 5, 4, 3, 2, 1]; 
var loopPromises = []; 
angular.forEach($scope.myArray, function (myItem) { 
    var deferred = $q.defer(); 
    loopPromises.push(deferred.promise); 
    //sample of a long-running operation inside loop... 
    setTimeout(function() { 
     deferred.resolve(); 
     console.log('long-running operation inside forEach loop done'); 
    }, 2000); 

}); 
$q.all(loopPromises).then(function() { 
    console.log('forEach loop completed. Do Something after it...'); 
}); 

这里是一个工作sample

0

您还可以使用map

var requests = cardTitles.map(function(title) { 
    var deferred = $q.defer(); 
    Trello.post('/path', {}, deferred.resolve, deferred.reject); 
    return deferred; 
}); 

$q.all(requests).then(function() { 

}); 

而且如果post方法已经返回了一个承诺:

var requests = cardTitles.map(function(title) { 
    return $http.post('/path/' + title, {}); 
}); 

$q.all(requests).then(function() { 

});