How does fetch work, and how do you handle errors with it?
Quick Answer
fetch(url) returns a promise that resolves to a Response. The catch: it only rejects on a network failure — a 404 or 500 still resolves. You must check response.ok (or response.status) yourself and throw. Body parsing (response.json()) is a separate promise.
fetch gives you a promise for a Response object. The thing everyone gets caught by is that it doesn't reject for HTTP error statuses — a 404 or a 500 is still a “successful” fetch as far as the promise is concerned. Only a network error rejects. So I always check response.ok and throw if it's false. Then reading the body is a second await — response.json(). For timeouts I use an AbortController and pass its signal. A lot of teams use axios instead because it handles the non-2xx rejection and JSON parsing automatically.
- Pattern:
const res = await fetch(url); if (!res.ok) throw new Error(res.status); const data = await res.json();. - Timeout / cancellation: pass
signalfrom anAbortController—fetch(url, { signal })thencontroller.abort(). fetchdoesn't send cookies cross-origin unlesscredentials: 'include'.- Libraries like axios add automatic JSON, non-2xx rejection, interceptors and timeouts — hence their popularity.