简体   繁体   中英

Add promise to $q.all()

I need to wait for several promises to finish before executing some code (angularJS):

var promises = [calculationPromise1, calculationPromise2];
$q.all(promises)
   .then(function(){
        notifyUser("I am done calculating!");
    });

In my case the user will be able to add new calculations at any time though. So if he adds a new calculation, the notification should be delayed further.

Modify the initial array

Sadly $q.all does not listen for changes on the promise-array, so executing this does not have any effect:

promises.push(newCalc);

Create a new $q.all-promise

This does not work either, because the notification will be shown multiple times instead of being delayed:

var promises = [calculationPromise1, calculationPromise2];
var qAllPromise; 

qAllPromise = $q.all(promises)
   .then(function(){
         notifyUser("I am done calculating!");
    })

function addAnotherCalculation(calc){
   qAllPromise = $q.all([calc, qAllPromise])
     .then(function(){
         notifyUser("I am done calculating!");
     })
}    

recursive call

recursively calling $q.all and executing the .then block only once should work:

var promises = [calculationPromise1, calculationPromise2];

function notifyWhenDone() {
$q.all(promises)
   .then(function() {
      if(allPromisesResolved()){
          notifyUser("I am done calculating!");
      }
      else {
          notifyWhenDone();
      }
    })
}

function addAnotherCalculation(calc){
   promises.push(calc);
}

My problem with this is that angular does not offer an API to check the status of promises which i would need in an allPromisesResolved function. I could check for promise.$$state.status === 1 to identify resolved promises, but i would rather not use internal variables ( $$state ) if i don't have to.

Question

Is there an easy way to add promises to a $q.all promise or can you think of an alternative solution to wait for a dynamically growing number of promises?

You can accomplish this with recursion. You can empty your promises array each time you call $q.all() and then check whether it has any new values when you get to the then() handler:

var promises = [calculationPromise1, calculationPromise2];

function waitForPromises(completedSoFar) {
    var p = $q
        .all((completedSoFar || []).concat(promises))
        .then(function (results) {
             return promises.length
                 ? waitForPromises(results)
                 : results;
        });

    promises = [];

    return p;
}

waitForPromises().then(function (results) {
    // all done
});

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