Fetch API Basics
The Fetch API provides the browser interface for making asynchronous HTTP requests and processing responses. It uses Promises, supports common HTTP methods and request options, and lets frontend code inspect response metadata and consume response bodies.
`fetch()` starts an HTTP request and returns a Promise that fulfills with a `Response` object when a response is received. The Promise does not normally reject merely because the server returns an HTTP error such as 404 or 500; those statuses must be checked explicitly with `response.ok` or `response.status`.
A request can specify options such as `method`, `headers`, `body`, `credentials`, and `signal`. For JSON APIs, a common pattern is to send `Content-Type: application/json` and serialize the payload with `JSON.stringify()`.
A `Response` exposes metadata such as `status`, `headers`, and `ok`. Its body is consumed asynchronously with methods such as `json()`, `text()`, `blob()`, or `arrayBuffer()`. Body consumption is generally a one-time operation, so code should avoid trying to read the same response body twice unless it uses an appropriate mechanism such as `response.clone()`.
In frontend applications, robust Fetch code usually handles both transport-level failures and application-level HTTP failures. An `AbortController` can cancel an in-progress request, which is useful when a component unmounts, a newer search supersedes an older one, or a request exceeds a chosen timeout.
Key points
- `fetch()` returns a Promise for a `Response`.
- HTTP 4xx and 5xx responses do not automatically cause `fetch()` to reject.
- Check `response.ok` or `response.status` before treating an HTTP response as successful.
- Use `response.json()` or another body-reading method to asynchronously consume the response body.
- Use request options such as `headers`, `body`, `credentials`, and `signal` when needed.
- Use `AbortController` when a request may need cancellation.
Interview questions
How can you cancel a Fetch request?
Create an `AbortController` and pass its `signal` in the fetch options. Calling `controller.abort()` signals cancellation of the associated request. Code should handle the resulting rejection appropriately, especially when cancellation is expected rather than an application error. This is useful for cleanup and for replacing obsolete requests.
What is the difference between `response.json()` and `JSON.parse()`?
`response.json()` asynchronously reads the response body and parses it as JSON, returning a Promise. `JSON.parse()` synchronously parses a string that you already have in memory. With Fetch, `response.json()` is normally the convenient choice because the response body is a stream rather than an already available JavaScript string. Both can fail when the underlying content is not valid JSON.
Does `fetch()` reject when the server returns a 404?
Normally, no. A 404 is still an HTTP response, so the fetch Promise can fulfill with a `Response` whose `status` is 404 and whose `ok` value is false. Application code should check `response.ok` or inspect `response.status` and handle unsuccessful statuses explicitly. Network-level failures are different because they can cause the Promise to reject.
How do you send JSON with Fetch?
Set the request method to an appropriate value such as `POST`, set the `Content-Type` header to `application/json`, and serialize the JavaScript value with `JSON.stringify()`. The server can then parse the request body as JSON. The response should be handled separately, including checking its HTTP status before parsing it when appropriate.
What does `fetch()` return?
`fetch()` returns a Promise. When the request receives a response, the Promise fulfills with a `Response` object. The response body is not automatically converted to JSON or text; it must be consumed with a method such as `json()` or `text()`. A rejected Promise generally represents a failure to complete the fetch operation rather than an HTTP status like 404.