When That's Not So Fetch: Error Handling With fetch() 
Tags: javascript, react, beginners
Published: 2021-06-25 18:01:40

The **fetch()** method in JavaScript is a global, asynchronous method that allows us to interface with API's for requests and responses. While this is a powerful and commonly-used tool, its error handling process may seem a bit elusive at start.

###Why Error Handling?
When errors are encountered during a `fetch()` call, it is often necessary to halt the compiler from reading the next few lines of code. To do so, the method call should throw an error upon encountering one. The thrown error can be "caught" later on for an alternate behavior to take place. Although one might think that the `fetch()` call would automatically throw an error upon encountering one, that is not the case for JavaScript.

According to the **[fetch() MDN](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)**, the **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)** object returned by the `fetch()` call is rejected (throws an error) only when "a network error is encountered." This means that `fetch()` Promises *do* resolve despite encountering client-side HTTP errors such as 404 and *do not* throw errors during the fetch. Therefore, the code shown below would log "Success" instead of "Error" when run, which may seem unexpected.

```js
fetch(url) // encounters a 404 error
   .then(res => res.json()) // no error is thrown
   .then(() => console.log("Success")) // 
   .catch(() => console.log("Error")) // fails to catch error
```
Luckily, you can fix this quite simply by using proper error handling.

###Handling fetch() Errors
`fetch()` calls can be made using either Promise chains or Async/Await. Fortunately, the error handling process is similar for both.

####Using Promises
The fetch API provides an `ok` property to the Promise response which indicates whether the HTTP status is within the range 200-299 (inclusive). This can be used to check whether any error is encountered during fetch.

```js
const handleError = response => {
   if (!response.ok) { 
      throw Error(response.statusText);
   } else {
      return response.json();
   }
}; //handler function that throws any encountered error

fetch(url)
   .then(handleError) // skips to .catch if error is thrown
   .then(data => console.log("Does something with data"))
   .catch(console.log); // catches the error and logs it
```

> The error-handler function should be called before the Promise response is parsed by `.json()`. Otherwise, the `.json()` method would strip out the response properties necessary for error handling (such as `ok`, `status`, and `statusText`).

####Using Async/Await
Error handling using Async/Await uses a slightly different syntax, but it also revolves around the idea of using the `ok` property to check whether any error is encountered or not.

```js
const response = await fetch(url);
if (!response.ok) {
   console.log(response.status, response.statusText);
} else {
   const data = await response.json();
   console.log(data);
}
```

> The `status` response property provides the status code (e.g. "404") while the `statusText` response property provides the status description (e.g. "Is Not Found").

###Conclusion
Although the error handling for `fetch()` may not seem intuitive at first, it will later make more sense since it provides the user with more control over unique situations.

Overall, error-handling for `fetch()` calls is a simple and user-friendly tool that will definitely aid you in the long-term.

###Resources
- [Handling Failed HTTP Responses With fetch()](https://www.tjvantoll.com/2015/09/13/fetch-and-errors/)
- [Error handling while using native fetch API in JavaScript](https://learnwithparam.com/blog/how-to-handle-fetch-errors/)
- [Using Fetch MDN](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)