Maksim Shamihulau
Maksim Shamihulau

Reputation: 1698

Why throw is delayed in async functions

Async functions somehow postpone(schedule) throw statements from immediate execution, while normal statements like console.log are executed immediately.

async function test() {
  console.log('before throw')
  throw 'error in test()'
}

test()
console.log('exit')

I would expect test() to be executed till the end, so no 'exit' to be printed to the console.

Upvotes: 0

Views: 795

Answers (2)

trincot
trincot

Reputation: 350137

By design, an uncaught error thrown in an async function will reject the promise that the async function returns. Quoting Mozilla Contributors:

Return value

A Promise which will be resolved with the value returned by the async function, or rejected with an exception thrown from, or uncaught within, the async function.

So at the time the exception is thrown, it is caught by the async function and dealt with to settle the promise it returns. The exception has been handled (not postponed), and the async function returns after which execution happily continues with console.log('test').

There is however another mechanism whereby the host will trigger an "unhandled promise rejection" event when a rejected promise has no rejection handler, which is the case in your code. This may look like your exception was delayed, but it is in fact a different mechanism which repeats the reason that the concerned rejected promise has. This event will only be triggered when the callstack is empty and it is clear that the rejected promise has no rejection handler.

Upvotes: 1

Bergi
Bergi

Reputation: 664297

Async functions somehow postpone(schedule) throw statements from immediate execution

No, they don't. The exception is thrown immediately when the function is called, and it does reject the promise returned by test(). A rejection which your code is ignoring, leading to an unhandled rejection! This is the (delayed) error you are seeing in red in the devtools console.
Notice that the behaviour of throw is no different than if the statement was executed after the test code had awaited something.

I would expect test() to throw an error as if test would be just a regular function, so no 'exit' to be printed to the console.

Well but test is not a regular function! Like any async function, it returns a promise. It will never throw an error when called.

Upvotes: 0

Related Questions