2014-04-03 18 views
9

Sto eseguendo il looping di un array con angular.forEach e chiamando una libreria ajax non angolare (Trello client.js). Il client ha callback "success" e "error", ma non restituisce un rinvio angolare. Vorrei eseguire una funzione una volta che tutte le chiamate ajax sono state completate.AngularJS attende tutte le chiamate asincrone all'interno della foreach finish

ho il seguente codice:

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

Che cosa posso fare in quel // TODO e nelle funzioni di callback in modo che le ultime 2 righe eseguiti solo dopo che tutti i messaggi sia esito positivo o negativo?

risposta

24

pseudo codice utilizzando il servizio $ q di angular.

requests = []; 

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

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

Penso che questo mi aiuti nella giusta direzione, ma Trello.post non restituisce una promessa. Quindi ho bisogno di collegarmi ai richiami che usano e ad una promessa angolare ... – Daniel

+1

Interessante, vedo che mi mancava nella tua domanda. Strano perché sembra che restituirebbe una promessa. Puoi fare qualsiasi cosa una promessa usando $ q.defer(). Aggiungerò pseudo codice ad esempio. –

+0

sì, l'ha fatto. L'api di Trello è asincrona, non solo promesse angolari, quindi si abbassa piacevolmente (ora che vedo come farlo;) Puoi accorciare un po 'semplicemente passando deferred.resolve e deferred.reject direttamente come i metodi di successo e callback di Trello, come questo: Trello.post ('/ path', {}, deferred.resolve, deferred.reject); – Daniel

3

Dai un'occhiata alla libreria asincrona https://github.com/caolan/async.

Quindi è possibile eseguire tutte le funzioni asyn in parallelo o in serie e la richiamata comune verrà eseguita al termine di tutte le operazioni.

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

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

Spero che sia d'aiuto.

+0

Non sarebbe forEachSeries' essere più appropriato del 'forEach' /' async? –

2

Semplicemente, si può fare in questo modo

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

Per chi cerca la risposta al di domanda del titolo "AngularJS attendere per tutte le chiamate asincrone di finitura interna foreach", qui è un modo generico per realizzarlo, anche utilizzando il servizio di $ q di angolare:

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

Ecco un sample lavoro.

0

È inoltre possibile utilizzare 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() { 

}); 

E se il metodo restituisce post già una promessa:

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

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

}); 
Problemi correlati