Most examples of using fetch()
are missing something very important. Here it is:
if (!response.ok) {
throw new Error(`Unexpected response status: ${response.status}`);
}
The quintessential fetch()
example from MDN itself looks like this:
fetch('http://example.com/movies.json')
.then((response) => response.json())
.then((data) => console.log(data));
Rewrite this as:
fetch('http://example.com/movies.json')
.then((response) => {
if (!response.ok) {
throw new Error(`Unexpected response status: ${response.status}`);
}
return response.json();
})
.then((data) => console.log(data));
To spare yourself the following problems:
-
Uncaught (in promise) SyntaxError: Unexpected token '<'
- This error baffles beginners all the time. This generally means the server returned an HTML response (often 404 "Not Found") so parsing it as JSON fails. - Crap data flowing through your application. Maybe the server responds with status 500 and
{ "error": "Internal Server Error" }
in the body, but your code treats it as a good response and it causes issues downstream, at best a mysterious error message.
The code I demonstrated which checks response.ok
isn't necessarily the exact code you should write. Sometimes a 404 or other "non-ok" response is actually perfectly "okay" and should not result in an error. The key is really just to check response.status
and handle it appropriately, rather than ignoring it and assuming everything is fine.
Learn more about response status codes and what they mean on MDN. Generally speaking, anything in the 200-299 range is an okay response. Anything 300-399 is redirection - you rarely have to worry about this because HTTP clients (including fetch) will automatically do the redirect for you. 400-499 indicates a "client error", these include validation errors, not found, that kind of thing. This range of errors indicates that the problem is with your request. Finally, 500-599 means there was some kind of error server-side. A response in this range should almost always be thrown as an error in your JS code (or retried).
response.ok
is the same as response.status >= 200 && response.status <= 299
Stay safe out there!