2014-04-03 4 views
9

Ich bin durch ein Array mit angular.forEach durchschleifen und eine nicht-eckige Ajax-Bibliothek (Trello client.js) aufrufen. Der Client hat "Erfolgs-" und "Fehler" -Rückrufe, gibt jedoch keine Winkelrückstellung zurück. Ich würde gerne eine Funktion ausführen, sobald alle Ajax-Aufrufe abgeschlossen sind.AngularJS warten auf alle async Anrufe innerhalb foreach Ende

Ich habe den folgenden 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] = '';  
      }; 

Was kann ich in diesem // TODO tun und in den Callback-Funktionen, so dass die letzten 2 Zeilen nur nach all den Pfosten laufen entweder Erfolg oder Misserfolg?

Antwort

24

Pseudo-Code mit eckigen $ 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 
}); 
+0

Ich denke, das bringt mich in die richtige Richtung, aber Trello.post gibt kein Versprechen ab. Also brauche ich einen Haken in die Callbacks, die sie verwenden und ein eckiges Versprechen ... – Daniel

+1

Interessant, ich sehe, dass ich das in Ihrer Frage vermisste. Seltsam, weil es so aussieht, als würde es ein Versprechen geben. Sie können alles mit $ q.defer() versprechen. Ich werde Pseudo-Code zum Beispiel hinzufügen. –

+0

Yep, das hat es getan. Trellos api ist asynchron, nur nicht eckig, also passt es gut (jetzt, wo ich sehe, wie es geht;) Sie können etwas verkürzen, indem Sie deferred.resolve und deferred.reject direkt als Trellos Erfolgs- und Rückruf-Methoden übergeben: Trello.post ('/ Pfad', {}, latent.resolve, deferred.reject); – Daniel

3

Werfen Sie einen Blick auf die Async-Bibliothek https://github.com/caolan/async.

So können Sie entweder alle Ihre asyn Funktionen parallel oder seriell ausführen und Ihr gemeinsamer Callback wird ausgeführt, sobald alle fertig sind.

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

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

Hoffe es hilft.

+0

Würde nicht async des 'forEach' /' forEachSeries' besser geeignet sein? –

2

einfach, Sie dieses

tun können
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

für die Suche nach der Antwort suchen, um den Titel Frage „AngularJS für alle Asynchron-Anrufe innerhalb foreach Finish warten“, hier ist eine generische Art und Weise zu erreichen, ist es, auch die Winkel $ q-Dienst:

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

Hier ist ein funktionierendes sample.

0

Sie können auch map verwenden:

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

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

}); 

Und wenn die post Methode gibt bereits ein Versprechen:

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

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

});