17

What exactly is the difference between these two statements?

funcThatReturnsAPromise()
  .then(() => { /* success */ })
  .catch(() => { /* fail */ });


funcThatReturnsAPromise()
  .then(() => { /* success */ }, () => { /* fail */ });
ffxsam
  • 26,428
  • 32
  • 94
  • 144
  • http://stackoverflow.com/questions/24662289/when-is-thensuccess-fail-considered-an-antipattern-for-promises has much better detail & answer, BUT I'm thankful for this one because it perfectly matches how I would formulate the question :) – conny Apr 04 '17 at 06:58

3 Answers3

11

Besides .catch(fn) being a shortcut for .then(null, fn), the difference in your examples is that

funcThatReturnsAPromise()
  .then(() => { /* success */ })
  .catch(() => { /* fail */ });

// is equivalent to

const p1 = funcThatReturnsAPromise()
const p2 = p1.then(() => { /* success */ })
const p3 = p2.catch(() => { /* 
   executed if p1 is rejected
   executed if p2 is rejected 
*/ })

While the second one is

funcThatReturnsAPromise()
  .then(() => { /* success */ }, () => { /* fail */ });

// equivalent to

const p1 = funcThatReturnsAPromise()
const p2 = p1.then(
  () => { /* success */ },
  () => { /*
     executed if p1 is rejected
     (p2 will be actually resolved by the result of this function only when p1 is rejected)
  */ }
);
Mauricio Poppe
  • 4,817
  • 1
  • 22
  • 30
  • thank you for explaining I was just trying to find documentation regarding that how it is beneficial, If I pass error function in .then() 2nd argument – Danish Jul 16 '18 at 22:28
  • `.catch(fn)` is equal to `.then(undefined, fn)` not `.then(null, fn)`. – Sagar Sep 23 '20 at 12:31
  • I checked this implementation https://github.com/then/promise/blob/master/src/es6-extensions.js#L117-L119 and it's null, regardless the spec https://promisesaplus.com/#the-then-method says that it could be anything but a function – Mauricio Poppe Sep 23 '20 at 15:35
11

.catch(foo) is equal to .then(undefined, foo)

But there is a difference between your code samples:

funcThatReturnsAPromise()
  .then(() => { /* success case of funcThatReturnsAPromise */ })
  .catch(() => { /* both fail case of funcThatReturnsAPromise 
                     and fail case of "then" function */ });


funcThatReturnsAPromise()
  .then(() => { /* success case of funcThatReturnsAPromise */ }, 
        () => { /* fail case of funcThatReturnsAPromise */ });
ykaragol
  • 6,139
  • 3
  • 29
  • 56
4

then(..) takes one or two parameters, the first for the fulfillment callback, and the second for the rejection callback. If either is omitted or is otherwise passed as a non-function value, a default callback is substituted respectively. The default fulfillment callback simply passes the message along, while the default rejection callback simply rethrows (propagates) the error reason it receives. catch(..) takes only the rejection callback as a parameter, and automatically substitutes the default fulfillment callback, as just discussed. In other words, it’s equivalent to then(null,..) :

p . then ( fulfilled );
p . then ( fulfilled , rejected );
p . catch ( rejected ); // or `p.then( null, rejected )`

then(..) and catch(..) also create and return a new promise, which can be used to express Promise chain flow control. If the fulfillment or rejection callbacks have an exception thrown, the returned promise is rejected. If either callback returns an immediate, non-Promise, non-thenable value, that value is set as the fulfillment for the returned promise. If the fulfillment handler specifically returns a promise or thenable value, that value is unwrapped and becomes the resolution of the returned promise.

—from "You Don't Know JS, Kyle Simpson

bullzito
  • 357
  • 1
  • 7