JavaScript Node.js Basics Handling Errors in Node Handling Parsing Errors with try and catch

Why use try/catch in ASYNC code?

Hi. I have read some discussions and some people pointed out that we use try/catch in order to catch errors in synchornous code which is OUTSIDE of the request to the api

and we use request.on('error') to catch errors happening during the ASYNCHRONOUS operation.

but here Andrew is using try/catch inside the async operation.

i have read this article: https://nodejs.org/zh-cn/knowledge/errors/what-is-try-catch/

and they mention this sentence: In the core node.js libraries, the only place that one really needs to use a try-catch is around JSON.parse()

so is this a special case or im right?

2 Answers

Michael Hulet
MOD
Michael Hulet
Treehouse Moderator 47,034 Points

You wrap a call in try/catch if there's a chance it could fail and throw an error. JSON.parse is a notable example because you don't know if the data you're passing into it is valid JSON until you try to parse it, and if it's not, it'll throw an error and crash your program

The reason you don't need to try/catch most errors in Node/Express is because they're greatly built around the idea that the code you write with it is very asynchronous. Code that runs asynchronously usually can't really throw, because by the time it does anything, the code that called it has already moved on, and it's no longer possible that it's within the scope of a try/catch block. Thus, the only way to give errors traditionally was either using events (request.on("error")), or passing them directly as a parameter to a callback function, which is how Node/Express have traditionally handled executing asynchronous code

However, ES2015 introduced a new construct: async/await. These combine to make asynchronous code look and act pretty much just like normal synchronous code. Thanks to this, it makes it possible for asynchronous code to return values and throw errors again. For example, let's imagine a function called fetch that just downloads data from the network. Using the traditional callback pattern, calling that function might look something like this:

fetch("https://teamtreehouse.com", (error, data) => {
    if (error) {
        console.error("There was an error!");
        console.error(error);
    }
    else {
        console.log(data);
    }
});

Here, it's not really possible for fetch to throw an error since it's asynchronous, so it just passes it as an argument to the callback function it's given. Now, let's see the same code written with async/await:

try {
    const data = await fetch("https://teamtreehouse.com");
    console.log(data);
}
catch(error){
    console.error("There was an error!");
    console.error(error);
}

This code looks really synchronous, though it technically functions asynchronously. This code pauses while fetch downloads its data, then continues like normal. Because of this, it can throw errors again instead of having to pass it to some kind of callback, and just return the data it downloads directly. So, if you're using async/await, it's a good idea to wrap all (or, at least, most, where it makes sense) of your async calls in try/catch statements so you can handle any errors that the asynchronous function throws without crashing your program

So basically we use try/catch to catch errors inside the response and outside the response?