0

I need to wait until all promises are resolved or rejected and only then execute a callback. It seems that the current implementation of Q triggers a callback as soon as one promise is rejected, here is the test:

var ps = [];
var d1 = $q.defer();
var d2 = $q.defer();
ps.push(d1.promise, d2.promise);

setTimeout(function () {
    d1.reject()
}, 2000)

setTimeout(function () {
    d2.resolve()
}, 5000)

$q.all(ps).then(function () {
    // is not triggered
}).catch(function () {
    //triggered after 2000 ms, I need this triggered after 5000ms
})

How can I achieve what I want?

Max Koretskyi
  • 101,079
  • 60
  • 333
  • 488
  • 1
    `promises.all` rejects all promises if any one of them is rejected. It's the basic behavior of the promise spec. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all. – Swaraj Giri Sep 23 '15 at 05:00

1 Answers1

3

You can use $q.allSettled() instead of $q.all() if you want to know when all the promises have finished (either fulfilled or rejected).

If you then want to know which promises were rejected, you will have to iterate through the returned results to query which ones were rejected. The Q doc has an example usage for $q.allSettled().

Copied from the Q documentation:

Q.allSettled(promises)
.then(function (results) {
    results.forEach(function (result) {
        if (result.state === "fulfilled") {
            var value = result.value;
        } else {
            var reason = result.reason;
        }
    });
});
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • thanks a lot, is there anything similar in ES6 promises? I can't find a good comparison between `Q` and ES6 promises, maybe you know a good resource to read? – Max Koretskyi Sep 23 '15 at 05:03
  • 1
    @Maximus - ES6 promises don't have an equivalent to `allSettled()`. It can be built yourself. You can see an implementation I wrote [here](http://stackoverflow.com/questions/32241391/wait-for-multiple-promises-to-be-rejected/32241993#32241993) using nothing but ES6 promises in a function I called `promiseSettle()`. It's not that hard to code. – jfriend00 Sep 23 '15 at 05:08
  • thanks, do you refer to `function promiseSettle(promises) {` function in the link as an equivalent of `allSettled`? And any good resource with a comparison? – Max Koretskyi Sep 23 '15 at 05:12
  • @Maximus - My `promiseSettle()` function in that answer is not an identical interface to `Q.allSettled()`, but it serves the same purpose and works similarly. I don't have a simple link for a comparison. ES6 promises are pretty bare. Libraries like Q and Bluebird offer a LOT of additional features over ES6 promises, many of which are very useful as soon as you start doing a lot with promises. You can see the [MDN description of ES6 promises here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) and compare it to what Q has. – jfriend00 Sep 23 '15 at 05:17
  • thanks! I'm mostly using `Q` now, but decided to switch to native Promises. Do you think it's not the time yet to give up `Q` in favour of native promises? – Max Koretskyi Sep 23 '15 at 05:22
  • 1
    @Maximus - I don't do my node.js development with only native promises. I find the advanced features that libraries like Q and Bluebird have are very useful and I've found no downside to using a superset replacement library like Q or Bluebird (personally I'm more familiar with Bluebird, but my understanding is that Q is similar). In browser JS development the one downside would be one more script in the page (though if you use a public CDN, it is probably already cached). – jfriend00 Sep 23 '15 at 05:30
  • Cool, thanks a lot for you help. I think I'll stick with `Q` for now since it's the part of the angular framework I use. Best of luck! – Max Koretskyi Sep 23 '15 at 05:45