DEV Community

loading...
Cover image for When That's Not So Fetch: Error Handling With fetch()

When That's Not So Fetch: Error Handling With fetch()

Anthony Chung
Aspiring full-stack software engineer looking for work. With my prior experience in materials science and bioengineering, I am proud to be a well-rounded, full-time nerd 🤓
Updated on ・3 min read

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, the 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.

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
Enter fullscreen mode Exit fullscreen mode

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.

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
Enter fullscreen mode Exit fullscreen mode

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.

const response = await fetch(url);
if (!response.ok) {
   console.log(response.status, response.statusText);
} else {
   const data = await response.json();
   console.log(data);
}
Enter fullscreen mode Exit fullscreen mode

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

Discussion (0)