0

Let's say I have a conditional statement after which a promise is created. I want to create a shared .catch() function that will be called every time any of my promises fail. However if I attach catch statements later - they are treated differently, why?

var p1;
var condition = true;

if (condition) {
  p1 = new Promise(function(resolve, reject) {
    setTimeout(function() { reject('BREXIT!'); }, 1000);
  });
} else {
  p1 = new Promise(function(resolve, reject) {
    setTimeout(function() { resolve('REMAIN!'); }, 1000);
  });
}

p1.catch(function(e) { console.error("1 I CATCH", e); } );
p1.catch(function(e) { console.error("2 I CATCH", e); } );
p1.then(function(e) { console.log("ALL DONE"); } );

// Actual output:
//
// 1 I CATCH BREXIT!
// 2 I CATCH BREXIT!
// Uncaught (in promise) BREXIT!
//
//==============================
// Expected output:
//
// 1 I CATCH BREXIT!
// ALL DONE

You can play with this code here: http://jsbin.com/lopuyid/edit?js,console

I do understand that I can solve this problem by moving the whole promise creation to separate function, and chaining everything. My question is why .catch() statements don't actually catch anything and are executed all, instead of one? Isn't chaining things A.f1().f2() the same as doing A.f1(); A.f2()?

Update

If someone will come to this page through web search, read the great links under this post. To quickly fix the problem, without too much code change, you should update the very same promise after each catch and then:

p1 = p1.catch(function(e) { console.error("1 I CATCH", e); } );
p1 = p1.catch(function(e) { console.error("2 I CATCH", e); } );
p1 = p1.then(function(e) { console.log("ALL DONE"); } );
Community
  • 1
  • 1
mseimys
  • 588
  • 1
  • 7
  • 16
  • 3
    You are registering multiple handlers on the same promise. If that promise rejects, then all `.catch()` handlers on the same promise will get called and none of the resolve handlers will be called on that promise. They are like event handlers. All the event handlers on the same promise get called. One does not affect the other. This is branching. What you are asking about is chaining. Try `p.catch().catch()`. That is chaining and will work differently. The first `.catch()` handler will affect the second in chaining. – jfriend00 Jul 12 '16 at 05:50
  • 1
    *"Isn't chaining things A.f1().f2() the same as doing A.f1(); A.f2()?"*. - No, it's not. When chaining, f1() will return a whole new promise with the added behavior (catch), which affects f2(). – noppa Jul 12 '16 at 06:09
  • 1
    See [Chaining vs. Branching](http://stackoverflow.com/questions/32216619/is-there-a-difference-between-promise-then-then-vs-promise-then-promise-then/32216660#32216660) and [Stacks vs. Chaining](http://stackoverflow.com/questions/29853578/understanding-javascript-promises-stacks-and-chaining/29854205#29854205). This `p.then(...); p.then(...)` is completely different than `p.then(...).then(...)`. – jfriend00 Jul 12 '16 at 06:43
  • 1
    In addition to @jfriend00 I want to point out that the two `catch` handlers perfectly catch the rejected `Promise`. The uncaught `Promise` is caused by the third `then` handler. But you can chain a catch handler of course: `p1.then(function(e) { console.log("ALL DONE"); } ).catch(() => console.log("BREXIT IS THE WRONG DECISION"));`. –  Jul 12 '16 at 08:16
  • Thanks guys for pointing me to those posts. Learned a lot! Honestly tried searching for an answer but did not manage to properly express myself to google search :) First time hearing word "branching" with promises... – mseimys Jul 13 '16 at 06:03

1 Answers1

0

From your code, what you expect is if reject occurs for the first time, 1 I CATCH BREXIT! should come up. If it occurs for the second time 2 I CATCH BREXIT! should come up. But that is not how javascript works. It is event based and you can register multiple actions for an event.

So basically, by doing:

p1.catch(function(e) { console.error("1 I CATCH", e); } );
p1.catch(function(e) { console.error("2 I CATCH", e); } );

you register 2 independent events which get triggered on reject.

kawadhiya21
  • 2,458
  • 21
  • 34