2017-05-31 1 views
0

Ceci est mon exigence avec AngularJS:boucle attendre jusqu'à ce que toutes les promesses sont résolues avant la prochaine itération

for (var i = 0, len = self.Scope.data.length; i < len; i++) 
{ 

     var data = self.Scope.data[i]; 
     var self = this; 
//First asynchronous function 
self.EcritureService.createNewData(data).then(() => { 
     })              
//Second asynchronous function 
self.OperationService.getOperation(data.idOperation).then((operation) => { 

     }) 
//Third asynchronous function 
self.AccountService.getAccount(data.codeCompte).then((compte) => { 
       currentAccount = compte; 
       currentAccount.montant = currentAccount.montant+data.montant; 
     }) 
//Fourth one relies on the third result, So it must be executed sequentially 
self.AccountService.updateAccount(currentAccount).then(() => { 
     })      
} 
// After all fetch loop's promises are resolved I want to execute some instructions here for to update the operation retrieved in the second function. 

Je veux cette boucle iterator attendre jusqu'à ce que toutes les promesses sont résolus avant de passer à l'étape suivante de faire en sorte que tous les les travaux se font, de passer à la dernière fonctionnalité qui résident à l'extérieur du bloc de boucle

+0

Pouvez-vous * s'il vous plaît * corriger votre indentation? – Bergi

+0

JavaScript est monothread. La boucle 'for' sera terminée ** avant que ** des promesses soient résolues. La boucle ne peut pas être faite pour attendre. – georgeawg

+0

Vous pouvez écrire votre logique comme si elle était synchrone, la mettre en fonction, et exécuter cette fonction via l'exécuteur synchrone [nsynjs] (https://github.com/amaksr/nsynjs). Voir la fonction "processus()" dans un exemple similaire ici: https://github.com/amaksr/nsynjs/blob/master/examples/browser-ajax-seq.js – amaksr

Répondre

0

Créer des tableaux de promesses et d'utiliser $q.all(promise_array) à exécuter lorsque toutes les promesses sont résolues

// map array of `$q.all()` promises 
let promises = self.Scope.data.map((data) => { 
    //First asynchronous function 
    let promise_1 = self.EcritureService.createNewData(data).then(() => {}) 
    //Second asynchronous function 
    let promise_2 = self.OperationService.getOperation(data.idOperation).then((operation) => { 

    }) 
    //Third asynchronous function 
    let promise_3 = self.AccountService.getAccount(data.codeCompte).then((compte) => { 
    currentAccount = compte; 
    currentAccount.montant = currentAccount.montant + data.montant; 
    return currentAccount; 
    }).then((currentAccount) => { 
    //return promise of 4th inside `then()` of third 
    return self.AccountService.updateAccount(currentAccount).then(() => {}); 
    }); 

    // this `$q.all()` resolves when this mapped instance of above all resolve 
    return $q.all([promise_1, promise_2, promise_3]); 

}); 

// resolves when all the loop instances of `$q.all()` resolve 
$q.all(promises).then(()=>{ 
    // run completion code here 
}).catch(err=>{ 
    console.log('Something failed in promise chain') 
}) 
+0

Ha - c'est magnifique :) Le tableau de $ q .all est alors $ q.all'ed - adore ça :) Bien mieux qu'une boucle récursive! – IrishDubGuy

0

Tout d'abord, je dirais que vous ne voulez probablement pas que ces services soient des promesses, étant donné que vous essayez de contourner la «promesse» d'entre eux. Donc, la solution la plus simple serait de réécrire les services pour qu'ils reviennent simplement au lieu d'une promesse.

Mais pour répondre à vos questions. Deuxième première partie - la meilleure façon de lier la 4ème promesse au 3ème est juste de le mettre à l'intérieur du 3ème .alors, comme ceci:

//Third asynchronous function 
self.AccountService.getAccount(data.codeCompte).then((compte) => { 
      currentAccount = compte; 
      currentAccount.montant = currentAccount.montant+data.montant; 
      //Fourth one relies on the third result, So it must be executed sequentially 
      self.AccountService.updateAccount(currentAccount).then(() => { 
    }) 
}) 

Si vous mettez toute erreur de manipulation, alors, vous pouvez décider de mettre la promesse imbriquée dans une clause .finally à la place. En ce qui concerne l'attente de la boucle, les boucles ne sont pas conçues pour cela. Le moyen le plus simple d'y parvenir serait d'écrire votre propre boucle et d'utiliser $ q.all pour regrouper les promesses. Vous devez garder une trace d'un compteur de boucle, que vous incrémentez dans le .then de $ q.all et utiliser une fonction récursive qui éclate lorsque le nombre requis de boucles est fait.