What is fetch
?
The fetch API is an awesome new addition to the web. As the name suggests it makes fetching things a lot easier. It is based on Promises which therefore support then
and catch
.
However many developers are a bit confused about the behaviour of fetch on http error codes.
fetch('https://httpstat.us/404')
.then(() => console.log('success')) // <--
.catch(() => console.log('failure'));
On first look you might think that this code logs failure to the console, but as soon as you try it, you'll see that it doesn't instead logs success.
Why doesn't it reject on http error codes?
...
How can we make it reject on http error codes?
The solution is quite simple! The Response
object returned by fetch
contains a Response.ok
property which according to MDN:
[states] whether the response was successful (status in the range 200-299) or not.
We can make use of this really neat boolean and write a simple response handler that sits between fetch
and your first actual then
:
const handler = response => {
if (!response.ok) throw new Error(response.status);
return response;
};
// prevent an infinite recursion
const clone = fetch;
// overwrite global fetch to always use the handler
fetch = (...args) => clone.apply(null, args).then(handler);
Our handler is a simple function which takes a Response
object as first parameter, checks if ok
is false
and if so, throws an Error containing the http error code.
If we now try to use our improved fetch
you'll see that our initial code returns "failure" as expected.
fetch('https://httpstat.us/404')
.then(() => console.log('success'))
.catch(() => console.log('failure')); // <--
Keep in mind that this overwrote fetch
globally which could break other libraries. If you just want to use the handler with specific calls, do the following:
fetch('https://httpstat.us/404')
.then(handler) // <-- handler
.then(() => console.log('success')) // <-- actual then()
.catch(() => console.log('failure'));
If you'd like to use this in a project of yours, I created an npm package for it.