Compare these 2 snippets:
try {
console.log('start')
const test = (() => {
console.log('inside')
const a = null;
a.c = 1
})()
console.log('end')
} catch (error) {
console.log('nvmnghia');
console.error(error);
}
// prints:
// start
// inside
// nvmnghia
// TypeError: set props of null
try {
console.log('start')
const test = (async () => { // Note the async without await
console.log('inside')
const a = null;
a.c = 1
})()
console.log('end')
} catch (error) {
console.log('nvmnghia');
console.error(error);
}
// prints:
// start
// inside
// end
// undefined, due to normal return
// Uncaught (in promise) TypeError: ...
// and no nvmnghia, which means the error wasn't caught indeed
Why does it behave this way? I’m surpise cuz my mental model for async
/promise has always been that the part before the first await
is run synchronously i.e. NOT scheduled in a microtask.
2
Answers
When your code is run synchronously, the errors get caught immediately by try/catch. When it is async, even if there is no await used, the function returns a promse, and errors are then instead handled by the error of the promise. These errors don’t get caught by a try/catch, so you’ll need to use .catch() or await.
JS engine handles asynchronous request in form of events. So, catch block can’t handle async error. You can handle that error in promise catch like below:
You will see
Catch from promise block:
in output before error.