4

While playing around with Promises to understand how they work, I noticed something I can't explain.

Given this example:

var A = function () {
    return Promise.resolve();
};

var B = function () {
    return Promise.reject();
};

var c = A();
var d = B();

c.then(
  function () { console.log('A success'); },
  function () { console.log('A fail'); }
);

d.then(
  function () { console.log('B success'); },
  function () { console.log('B fail'); }
);

Promise.all([c, d]).then(
  function () { console.log('all success'); },
  function () { console.log('all fail'); }
);

First the single resolve/reject callbacks fire, followed by the reject callback of Promise.all. This is expected because B rejects the Promise.

But when written like the, the resolve callback of Promise.all fires:

var A = function () {
    return Promise.resolve();
};

var B = function () {
    return Promise.reject();
};

var c = A().then(
  function () { console.log('A success'); },
  function () { console.log('A fail'); }
);
var d = B().then(
  function () { console.log('B success'); },
  function () { console.log('B fail'); }
);

Promise.all([c, d]).then(
  function () { console.log('all success'); },
  function () { console.log('all fail'); }
);

This is unexpected since one of the two Promises is rejected, so the Promise returned by all should be rejected too.

What is happening here – does is have something to do with return values? Do I need to return a new Promise somewhere?

Sven
  • 12,997
  • 27
  • 90
  • 148
  • Totally expected behavior, because your handling the exeption.. Don't handle your expections, and then your all will catch them. Or alternatively return a rejection in your rejection handlers. – Keith Nov 04 '16 at 23:32
  • You are not waiting for `B`, you are waiting for the promise returned by `B`'s `then`. – mrmcgreg Nov 04 '16 at 23:32
  • In the first one you've already caught the error in the first `then` call, and the promise chain resets itself after that, as the error has been handled. – adeneo Nov 04 '16 at 23:35
  • See also [When is .then(success, fail) considered an antipattern for promises?](http://stackoverflow.com/questions/24662289/when-is-thensuccess-fail-considered-an-antipattern-for-promises) – guest271314 Nov 05 '16 at 00:12

2 Answers2

0

Your two examples look similar, but are not identical. Here is the documentation for then (emphasis mine):

Calls onFulfilled or onRejected with the fulfillment value or rejection reason of the promise (as appropriate) and returns a new promise resolving to the return value of the called handler.

In your first example, d is set to the result of B(), which is a rejected promise. A new promise means that something is logged, but d is not changed.

In your second example, d is changed to the result of B().then(...), which is a resolved promise.

You probably want to throw in your rejection handler.

Wander Nauta
  • 18,832
  • 1
  • 45
  • 62
0

You are suppressing error in the second case:

// d is promise which suppressed error from B()
var d = B().then(
  function () { console.log('B success'); },
  function () { console.log('B fail'); }
);

You should re-throw error if you want d to be rejected as well:

var d = B().then(
  function () { console.log('B success'); },
  function (e) { console.log('B fail'); throw e; }
);
madox2
  • 49,493
  • 17
  • 99
  • 99