8

What are the differences between

?

Do the two JavaScript expressions always yield the same result, regardless of the content and state of myPromise and implementations of functions a and b?

Is there any situation where I should prefer using one over the other, other than code readability?

Ry-
  • 218,210
  • 55
  • 464
  • 476
Snackoverflow
  • 5,332
  • 7
  • 39
  • 69

3 Answers3

5

It is recommended to use catch(), Because when we use a myPromise.then(a, b), in a promise chain, Then next then block will always execute even if the promise is rejected. This is because the promise chains think that we have cleaned up the error in our error handler. Look at the example below: Even when we reject() the next then block executes.

function asyncFun(a,b){
  return new Promise((resolve, reject)=>{
      if(typeof a ==="number" && typeof b === "number")
        resolve(a + b);
      else
        reject("invalid data!!");
  });
}
asyncFun(2,'4').then((response)=>{
  console.log(response);
  return response;
}, (error)=>{
  console.log(error);
}).then((response)=>{
  console.log("console 2",response)
}, (error)=>{
  console.log(error);
});

While this will not happen if we use only a single error handler catch() at the end of the promise chain: please note As pointed out by Bergi that the above scenario will be reproduced even in case of mutiple catch().

function asyncFun(a,b){
  return new Promise((resolve, reject)=>{
      if(typeof a ==="number" && typeof b === "number")
        resolve(a + b);
      else
        reject("invalid data!!");
  });
}
asyncFun(2,'4').then((response)=>{
  console.log(response);
  return response;
}).then((response)=>{
  console.log("console 2",response)
}).catch((err)=> console.log(err));
amrender singh
  • 7,949
  • 3
  • 22
  • 28
  • 1
    It’s recommended to use `.catch()` when that’s what you want to do, not always. – Ry- Aug 05 '18 at 08:33
  • @Ry- Updated the answer, thanks :-) – amrender singh Aug 05 '18 at 08:40
  • 2
    Your example makes no sense: even if you had used two `catch` blocks, the next `then` callback would have been executed. The fix here was to drop one error handler, not to use a different `then` syntax. And no, as @Ry- said: it is not *generally* recommended to use `catch` – Bergi Aug 05 '18 at 09:35
  • So what you are trying to say is, if the first `then()` block would only have one argument, and the promise was rejected, then the second `then(func)` block would be skipped? If so, I think it could have a bit better wording, but thanks anyway for pointing me in the right direction! – Snackoverflow Aug 05 '18 at 10:40
3

These are different in the way they handle errors in the then() callback, which in some cases can be a significant enough difference that most people recommend only using catch().

For example with catch(), you can catch this error:

Promise.resolve('test')
.then(r => {
  throw("whoops")
})
.catch(e => console.log("caught error:", e))

Using the then(a,b) style you can't:

Promise.resolve('test')
.then(r => { throw("whoops")},
      e => console.log("caught error?", e))
// unhandled rejection (you'll need to look in the console)

Other than some testing scenarios, it's hard to think of a use case where this behavior would be preferred.

You can use both, which will catch rejections and errors in the then() callback, but this makes things more confusing than you probably need unless you have a special use case for distinguishing between these two kinds of errors. For example which handler handles which errors:

Promise.reject("rejected")
.then(r => {throw("whoops")}, 
     e => console.log("Promise 1: caught error in second function:", e))
.catch(e=> console.log("Promise 1: caught error in catch", e))

Promise.resolve("rejected")
.then(r => {throw("whoops")}, 
     e => console.log("Promise 2: caught error in second function:", e))
.catch(e=> console.log("Promise 2: caught error in catch", e))
Mark
  • 90,562
  • 7
  • 108
  • 148
  • 2
    Actually, wanting to handle rejections from only a certain promise is pretty common, it's not just "some testing scenarios". – Bergi Aug 05 '18 at 09:38
  • 1
    I like this answer a lot, it very well shows **the differences** between the two cases. Thanks! – Snackoverflow Aug 05 '18 at 10:37
-2

The 2 ways are the same, I think. However, I prefer using async().then().catch() because It will be easier to read.

Moreover, In case you want to call some async functions one by one, but need to break immediately (don't want the following function continue running) if some error throw. You need to put only 1 catch at the final. In this case, we can't use the first style.

asyncA()
    .then((val) => asyncB(val))
    .then((val) => asyncC(val))
    .then((val) => asyncD(val))
    .catch(() => { /* any of asyncA, asyncB, asyncC, asyncD will goes directly here if throwing error })

in the example above. You can see, any of the function async fails, the program will skip the following functions and goes directly to catch.

Dat Tran
  • 1,576
  • 1
  • 12
  • 16
  • They aren’t the same. – Ry- Aug 05 '18 at 09:04
  • How It's not the same? You can give an example in one style and I can solve it in the other style with the same result as you expected. – Dat Tran Aug 05 '18 at 09:17
  • The question asks for the difference between `p.then(a, b)` and `p.then(a).catch(b)`. That’s it, that’s the whole thing. Answering it with “the 2 ways are the same, I think” is wrong. See the upvoted answers for how they differ. – Ry- Aug 05 '18 at 09:24
  • I answered It's quite the same in the general usage. The difference is on coding style. And I also stated the only case that I think can be applied catch() only. So What you want more? – Dat Tran Aug 05 '18 at 09:28
  • @DatTran [They work very differently](https://stackoverflow.com/q/24662289/1048572), it's not at all just a difference in style – Bergi Aug 05 '18 at 09:39
  • I agreed on the difference in the way the engine handle the instruction. But on the style and the usage, I don't find the difference. especially, when you don't need so much micro-optimization, then using either is the same. – Dat Tran Aug 05 '18 at 09:59
  • 1
    It’s not an optimization. There is a practical and important difference in behaviour. – Ry- Aug 05 '18 at 10:08
  • The answer does have a point though, how the two cases can be used differently. If I want to skip the following `then()` blocks after a failure, I must not use a rejection handler (second argument). However, does a rejection handler also catch an `Error` that is `throw`-n from a previous block, or does it only handle rejected `Promise`-es? – Snackoverflow Aug 05 '18 at 10:46