0

I've got 2 promises in a try/catch block, with a third function afterwards using the awaited responses.

When I await res1 and res2 within the parameters of lastFunction, the error that is thrown is not caught by the catch block.

When I await them normally by const res2 = await promise2(), the error is caught in the catch block.

Why is this happening?

const handler = async () => {
  const results = await Promise.all(
    [1].map(async id => {
      try {
        const res1 = promise1()        
        const res2 = promise2() 
        const finalResponse = await lastFunction(await res1, await res2)
      } catch (err) {
        console.log('Catching error')
        console.log(err)
      }
    })
  )
}

const promise1 = () => {
  return new Promise((res, rej) => {
    setTimeout(() => res(1), 1000)
  })
}

const promise2 = () => {
  return new Promise((res, rej) => {
    throw new Error('second one broke')
  })
}

const lastFunction = (prom1, prom2) => {
   return new Promise((res, rej) => {
     res('done')
   })
}

handler();

CodePen: https://codepen.io/OliverNural/pen/oNbrMWw (Open console)

  • This SO post https://stackoverflow.com/questions/45285129/any-difference-between-await-promise-all-and-multiple-await/54291660#54291660 Solved the answer for me. It's to do with error handling with multiple `await`s, rather than using a `promise.all()` – Oliver Nural Jul 31 '20 at 14:05

1 Answers1

1

promise2 is throwing an error, not rejecting the promise. It doesn't matter where you await it, it still won't catch the error, since the error originates from the promise. If you change promise2 to properly reject the promise (rej("second one broke") instead of throw new Error("second one broke")), then you'll notice that the catch does in fact work.

Aplet123
  • 33,825
  • 1
  • 29
  • 55
  • I'm afraid if I put the `await` before the function call, it does catch it properly. You can test this in a pen like the above with that change. – Oliver Nural Jul 30 '20 at 14:50
  • I have, and it did not catch the error. – Aplet123 Jul 30 '20 at 14:51
  • Huh, my bad. I can't replicate it in Codepen as I thought. Something is different, I'll have a look at my code and your suggestion. – Oliver Nural Jul 30 '20 at 14:53
  • "*the error originates from the promise*" - to clarify, I'd say that the error is thrown from the `setTimeout` callback and *not* from the promise. The promise is totally unaffected, it is not getting rejected as it should. – Bergi Jul 30 '20 at 14:54
  • For some context, i'm using catch because I'm making HTTP calls in `promise1()` and `promise2()`, and i'm throwing the error handling up to the caller to handle. So perhaps Bergi is close? Apologies, didn't think it was related earlier. – Oliver Nural Jul 30 '20 at 15:06
  • Updated code, and pen, @Aplet123, without the setTimeout it can be recreated. Either an error thrown manually, or by my HTTP library results in the same behaviour. If you await, it gets caught. – Oliver Nural Jul 30 '20 at 15:24
  • Yes because then it's thrown in the promise context. But in your setTimeout example you break out of the promise context and is just asynchronously throw an error. It would work if you would use `await new Promise(resolve => setTimeout(resolve, 1000)); throw new Error('oops');` instead. You have to understand that `new Promise` allows you to run _non-promise code_ that controls the result of the returned promise. If you throw an error inside of that, you have to clean up for yourself. – CherryDT Jul 30 '20 at 20:01
  • Okay, I think I understand. So if I am handling a third party's error throwing inside my Promise, I have to handle that myself. However, I could then throw a normal error inside the Promise context, it would be handled correctly. So that would mean both functions would have to have a try/catch block. Is there a better way of handling this, with third party error code? Either way, thank you :) Could you recommend any resources to read up on this? – Oliver Nural Jul 31 '20 at 07:54