4

I am trying to catch an error caused by an async javascript callback function,

try{
  setTimeout(()=>{ 
    throw err 
    console.log("after throw") 
  }, 1000)
}catch(e){
  console.log("caught");
}

But as many of you may know catch block is never executed, so what exactly is happening here?

I know I can achieve similar thing using promises and async/await,

async foo(){
  try{
    await setTimeoutPromise(1000);
  }catch(e){
    alert("caught");
  }
}
4
  • or Error-handling try & catch + callback? Commented Aug 29, 2019 at 5:59
  • 1
    It's not quite the same. The scope of this question is more about the reason, not the workaround. Commented Aug 29, 2019 at 6:03
  • 1
    but the answers do include the reason, duplicate does not mean mirror images. Commented Aug 29, 2019 at 6:04
  • Don't throw exceptions in asynchronous callbacks. Throw them in promise callbacks instead. Commented Aug 29, 2019 at 8:15

2 Answers 2

1

When you use setTimeout, the callback gets pushed into the event loop (moved out of the JS Engine and into the realm of the runtime/browser) and your foo function exits immedeatly.

After the timeout AND once the stack is empty, the event loop will put the callback onto the stack and run it. That's why the try/catch and the callback are independent of each other. That's also why setTimeout(1000) does not mean in a second but not earlier than and somewhat close to one second.

See What the heck is the event loop anyway? | Philip Roberts | JSConf EU

Sign up to request clarification or add additional context in comments.

1 Comment

I should had probably given a better introspection before posting this.. :/
1

These are two different things.

The first code won't catch the error, since it happens asynchronously, and try...catch will only catch synchronously thrown exceptions.

The second code will catch the error, because await 'synchronize' the code (makes it look and work like it would've been synchronous), and the error thrown only by await: if you haven't been used it, you would get only a rejected promise (You can't really throw anything from an async function!)

To make the first code working, move the try...catch inside the callback:

setTimeout(()=>{ 
  try{
    throw err
  }catch(e){
    console.log('catched')
  }
  console.log("after throw") 
}, 1000)

2 Comments

I don't think it's accurate to say that async/await "synchronize" the code. It remains asynchronous, just easier to understand and deal with.
@lonesomeday Yes, I know, that's why I quoted the word 'synchronize'. I haven't found the accurate way to express what I would like to say... Now I've rephrased it, so it might be clearer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.