简体   繁体   中英

AngularJS wait for all async calls inside foreach finish

I am looping through an array with angular.forEach and calling a non-angular ajax library (Trello client.js). The client does have 'success' and 'error' callbacks, but doesn't return an angular deferred. I would like to execute a function once all of the ajax calls have completed.

I have the following code:

$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] = '';    
            };

What can I do at that //TODO and in the callback functions so that the last 2 lines only run after all the posts either succeed or fail?

pseudo code using angular's $q service.

requests = [];

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

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

For those looking for the answer to the question's title "AngularJS wait for all async calls inside foreach finish" , here is a generic way to achieve it, also using angular's $q service:

$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...');
});

Here is a working sample .

Have a look at the async library https://github.com/caolan/async .

So you can either run all your asyn functions in parallel or series and your common callback will be executed once all of them are finished.

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

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

Hope it helps.

Simply , you can do like this

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

You can also use 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() {

});

And if the post method already returns a promise:

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

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

});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM