Search code examples
javascriptpromisees6-promise

es6 Promises: exception thrown in a promise is not caught by the catch method


The following code

const run = async() => {
  try {
    const p = Promise.reject()
    p.catch(() => console.log('exception caught'))
    await p
    console.log('flow completed')
  } catch {
    console.log('flow interrupted')
  }
}
run()

Prints the following output:

exception caught
flow interrupted

Meaning, even though the catch method is running the exception is not caught

Now if i make this seemingly irrelevant edit and chain the catch right after the promise definition

const run = async() => {
  try {
    const p = Promise.reject().catch(() => console.log('exception caught'))
    await p
    console.log('flow completed')
  } catch {
    console.log('flow interrupted')
  }
}
run()

the output becomes

exception caught
flow completed

I tried defining the promise like const p = new Promise((resolve, reject) => {setTimeout(reject, 100)}) thinking it might matter if the catch was set before the promise rejection but it did not change anything

Im running these tests with node 12.16.1

Can anyone explain why is the exception not caught in the first code sample, but is caught in the second ?


Solution

  • You're forking your chain there. (Wow, that sounds weird…)

    You're doing the equivalent of this:

    const p = Promise.reject();
    p.catch(...);
    p.catch(...);
    

    Those are two separate forks in the promise chain which will be caught independently. p is rejected, p.catch recovers it for anything that comes after p.catch. Anything not chained to p.catch will experience the rejection of p independently. Since you await p, you're not in the caught fork of the chain.

    p is rejected and triggers any and all attached catch handlers, of which there can be more than one. p.catch(...) on the other hand returns a new successful promise.