2014-04-03 82 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() { 

});