简体   繁体   中英

How to have single finally handler for multiple promises in AngularJS?

I have two promises, independent of each other and I want to do a finally step after both of the promises are completed (either rejects or resolves).

$q.all() cannot be used as I want the finally to always execute (only once for both promises) even if any of the promises rejects

One solution could be to have a counter and have a finallyHandler function to execute it when both promises resolves/rejects.

  var count = 0;
  function finallyHandler() {
    if ( ++count === 2 ) {
      doStuff();
      count = 0;
      }
  }

firstPromise.finally(finallyHandler);
secondPromise.finally(finallyHandler);

This can work but doesn't look right.

Is there any better way to do this?

Promise.all(iterable) will do what you're looking for. Please have a look at the browser compatibility, however, as Internet Exploer does NOT support this method. From the documentation:

The Promise.all(iterable) method returns a promise that resolves when all of the promises in the iterable argument have resolved, or rejects with the reason of the first passed promise that rejects.

Using your code example (with failure behavior), it would look like this:

Promise.all([firstPromise, secondPromise]).then(values => { 
    finallyHandler();
}, reason => {
    finallyHandler();
});

Even though the failure block is the same as the success block, the success block only runs once all promises have completed successfully, and the failure block runs once (and only once) the first failure is encountered.

Reference:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

firstPromise().catch().secondPromise().catch().then(//what you want)

The above promise chain can achieve this. Final then would be called in all scenarios . catch would propagate the promise rejections.

Can you use?

Promise.All([array of promises],handler)

Promise.All Docs

Or libraries like BlueBird or Asyncjs ?

Normally $q.all resolves rejected on the first promise that gets rejected and doesn't wait for the other promises. To wait for all promise to resolve either fulfilled or rejected, make resiliant versions of each promise, then use $q.all on those:

var resiliantFirstPromise = firstPromise.catch(e => "CONVERTED");
var resiliantSecondPromise = secondPromise.catch(e => "CONVERTED");

$q.all([resiliantFirstPromise, resiliantSecondPromise])
  .then(() => {
    console.log("Both promises have resolved");
});

By returning a value to the .catch method, each promise that is rejected returns a derived promise that has been converted to a fulfilled promise. Since neither derived promise is rejected, the $q.all will wait for both promises to be resolved (either fulfilled or rejected.)

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