DEV Community

Cover image for Async/Await Traps: The importance of await in try/catch blocks
Ionel Cristian Lupu
Ionel Cristian Lupu

Posted on • Originally published at ionel-lupu.com

Async/Await Traps: The importance of await in try/catch blocks

Is the following code going to crash your program or will it execute without any issues? Take your time to make a guess.

async function canParkCar(car) {
    if ( !car.allowed ) {
        throw new Error(`${car.owner} is not allowed to park`)
    }

    // some async work

    return true
}

function parkCar(car) {
    try {
        return canParkCar(car)
    } catch ( error ) {
        console.log(error.message)
        return false
    }
}

const car1Parked = await parkCar({ owner : 'John', allowed : false })
if ( car1Parked ) {
    console.log(`car 1 parked`)
}

const car2Parked = await parkCar({ owner : 'Mark', allowed : true })
if ( car2Parked ) {
    console.log(`car 2 parked`)
}
Enter fullscreen mode Exit fullscreen mode

I was confused to see it's actually crashing EVEN if there is a try/catch block intended to handle any thrown errors:

$ node app.js

file: ./app.js:3
        throw new Error(`${car.owner} is not allowed to park`)
              ^
Error: John is not allowed to park
Enter fullscreen mode Exit fullscreen mode

My expectation was to see this in the console:

$ node app.js

John is not allowed to park
car 2 parked
Enter fullscreen mode Exit fullscreen mode

One thing you need to be careful regarding try/catch blocks and promises is to properly use the await keyword
depending on where you want to catch the errors.
In the example above, at this line

return canParkCar(car)
Enter fullscreen mode Exit fullscreen mode

the parkCar function finished its job by just
returning a promise. The promise wasn't resolved, so no error was thrown.

However, when you use await on this line

await parkCar({owner: 'John', allowed: false})
Enter fullscreen mode Exit fullscreen mode

you are now waiting for the promise to resolve and implicitly waiting for any thrown errors. And because there is
no try/catch block around this await statement, the program crashes. The error bubbled up until the "root" of the
program.

The fix? Just await the canParkCar call:

async function parkCar(car) {
    try {
        return await canParkCar(car)
    } catch ( error ) {
        console.log(error.message)
        return false
    }
}
Enter fullscreen mode Exit fullscreen mode

Now, the line

return await canParkCar(car)
Enter fullscreen mode Exit fullscreen mode

not only returns a promise, but it also waits for the promise to resolve. Any thrown errors will be handled there by
the try/catch block.

The program now has the expected output without any crashes:

$ node app.js

John is not allowed to park
car 2 parked
Enter fullscreen mode Exit fullscreen mode

The key takeaway? Be careful when you want to return a promise, or you want to actually resolve it depending on
your try/catch blocks.

That's it for this quick tip.

My Website: https://ionel-lupu.com/
My Twitter: https://twitter.com/ionelLupu_

Top comments (0)