Search code examples
javascriptexceptionasynchronous

Why error in the "synchronous" part of promise/async function is handled differently


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.


Solution

  • 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 promise, 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.