3

the promise gets resolved CB of then runs then it throws a rejected promise after that catch block runs so why the other then ran after that? i am not able to understand the flow behind it does catch also return a new promise?

code-

Promise.resolve()
  .then(() => {
    // Makes .then() return a rejected promise
    throw new Error('Oh no!');
  })
  .catch(error => {
    console.error('onRejected function called: ' + error.message);
  })
  .then(() => {
    console.log("I am always called even if the prior then's promise rejects");
  })

output- I am always called even if the prior then's promise rejects

onRejected function called: Oh no!

Yousaf
  • 27,861
  • 6
  • 44
  • 69
  • 2
    Yes, the `catch()` also [returns a Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch#syntax) – Pointy Jul 10 '21 at 12:49
  • and `.catch()` handles the rejection so the promise it returns is not a rejected one, but a fulfilled one – Bravo Jul 10 '21 at 12:53
  • Related: https://stackoverflow.com/questions/16371129/chained-promises-not-passing-on-rejection – Bergi Jul 10 '21 at 14:44
  • Once you are in `Promise` realm you will always be returned a `Promise`. So both `.catch()` and `.then()` returns a promise. What they return is all about what the provided callback returns. You may do a `.catch(e => (handleError(e), Promise.resolve(3)))` and continue with another `.then()` stage. – Redu Jul 11 '21 at 15:50

1 Answers1

1

Both then() and catch() methods return a promise and the promise they return depends on two things:

  • what happens to the original promise on which they are called?

  • What is returned from their callback function?

The last then() method is called on the promise returned by the catch() method and as the catch() method, in your code, implicitly returns undefined, the promise returned by the catch() method is resolved with the value of undefined which then invokes the then() method.

If you want to stop the execution of the last then() method, then you need to reject the promise returned by the catch() method. This can be done by either rethrowing the error or returning a rejected promise.


Your code is executed as described below:

  1. Promise.resolve() returns a resolved promise

  2. Resolved promise in step 1 leads to the invocation of the Promise.resolve().then(...) method's callback function

    • As the callback function of Promise.resolve().then(...) throws an error, the promise returned by the then() method is rejected with the error object as the rejection reason.
  3. As the promise returned by the then() method in step 2 is rejected, it leads to the invocation of the catch() method's callback function.

    • Callback function of the catch() method logs the error

    • As there is no explicit return statement in the callback function of the catch() method, the callback method implicitly returns undefined.

    • The promise returned by the catch() method is resolved with the return value of its callback function, i.e. undefined

  4. As the promise returned by the catch() method is resolved, it invokes the callback function of the last then() method

Yousaf
  • 27,861
  • 6
  • 44
  • 69
  • why the last then console.log() ran before the catch one ? – Rohan Sharma Jul 10 '21 at 12:55
  • `console.error` in the `catch()` method is executed _before_ the `console.log` in the last `then()` method. – Yousaf Jul 10 '21 at 12:57
  • it didn't run **before** the catch one – Bravo Jul 10 '21 at 12:58
  • i ran it on this site https://onecompiler.com/javascript/3x52gcwsz I am always called even if the prior then's promise rejects onRejected function called: Oh no! this was the result but here on run code snippet it works exactly the same way you explained. – Rohan Sharma Jul 10 '21 at 13:08
  • thans a lot your your help. – Rohan Sharma Jul 10 '21 at 13:08
  • `catch()` method's callback function will execute before the last `then()` method's callback. That difference in output is probably because `console.error` writes to `stderr` whereas `console.log` writes to `stdout`. Try changing `console.error` to `console.log`. – Yousaf Jul 10 '21 at 13:14