JavaScript Fetch API
The Fetch API is a modern JavaScript interface for making network requests with improved simplicity and flexibility compared to XMLHttpRequest.
The Fetch API is a key feature in JavaScript that lets you make network requests (download data, submit forms, talk to APIs) and returns a Promise. It is the modern replacement for the older XMLHttpRequest and pairs naturally with async/await. This guide covers the common patterns: GET and POST requests, inspecting the response, reading JSON and text, sending headers, and handling errors — using the free JSONPlaceholder API for runnable examples.
Understanding the Fetch API
The Fetch API is built for network communication and uses a promise-based system to retrieve resources. It's flexible enough to manage different data formats and complex requests, making it an excellent choice for developing web applications.
The basic signature is fetch(url, options). It returns a promise that resolves to a Response object as soon as the server responds with headers — before the body has finished downloading. You then read the body separately with a method like .json() or .text(), each of which returns its own promise.
A critical gotcha: fetch() only rejects on a network failure (no connection, DNS error, CORS block). It does not reject on HTTP error statuses like 404 or 500 — those still resolve successfully. You must check response.ok (or response.status) yourself.
Basic Usage of Fetch
Let's dive into a basic example of fetching data from a JSONPlaceholder post:
This snippet fetches data from a specific post, demonstrating how Fetch returns a promise that resolves to the response of the request. The response is then parsed as JSON and output to the console.
Inspecting the Response
The Response object carries useful metadata before you even read the body. The most important properties are:
response.ok— a boolean that istruefor status codes in the 200–299 range.response.status— the numeric HTTP status code (e.g.200,404,500).response.statusText— the text message that goes with the status (e.g."OK").response.headers— aHeadersobject you can query with.get().
Reading the Body: .json() vs .text()
The body of a response can be read in several formats. Each method returns a promise and can only be called once per response — the body is a stream that gets consumed:
response.json()— parses the body as JSON and resolves to a JavaScript object or array.response.text()— resolves to the raw body as a string. Useful for plain text, HTML, or when you want to handle JSON parsing yourself.response.blob()— resolves to aBlob, for binary data like images or files.
Error Handling in Fetch
Handling errors is critical when working with network requests. Because fetch() does not throw on HTTP error statuses, the standard pattern is to check response.ok and throw your own error when it is false. Here's an example incorporating error handling:
In this example, we check if the response is successful; if not, an error is thrown. The .catch() method catches any errors, maintaining the integrity of the application.
Implementing a POST Request
The Fetch API is not limited to GET requests; it's equally adept at handling POST requests to send data to a server. Pass a second argument with method, a body, and headers. When sending JSON, you must both serialize the body with JSON.stringify() and set the Content-Type header so the server knows how to parse it. Here’s how to create a new post with JSONPlaceholder:
This code snippet demonstrates sending a POST request with JSON data, specifying the method, body, and headers. It illustrates the Fetch API's versatility in handling various request types.
Sending Custom Request Headers
Headers are how you tell the server about the request — the content type, the expected response format, or authentication credentials such as a bearer token. You can pass headers as a plain object, or build them with the Headers class for more control:
Note: a request to another origin will only succeed if that server allows it via CORS. See Fetch: Cross-Origin Requests for how cross-origin rules affect headers and credentials.
Leveraging Async/Await with Fetch
For a more elegant approach to asynchronous code, the Fetch API can be combined with async and await. This method offers a more readable syntax, akin to synchronous code:
Using async and await, this example fetches a post, awaiting the response and processing it within a try/catch block for error handling. It showcases how modern JavaScript features can simplify Fetch API usage.
Handling Errors with Async/Await
When it comes to error handling in async/await, it's typically done using try-catch blocks.
To handle errors that may occur during asynchronous operations, you can wrap your await calls within a try block and catch any errors that occur with a catch block. Here's how you can add error handling to the fetchData function:
Error Propagation
Error propagation is how an error "moves" or gets passed along from one part of your program to another. Think of it as the path an error takes after it happens. When an error occurs, it’s like dropping a ball. Error propagation is about where the ball goes after it’s dropped: does someone catch it, or does it hit the ground?
In JavaScript, this typically occurs through promise rejection chaining, where an unhandled rejection travels up the call stack until a catch block or global handler intercepts it.
In the example below, if you want errors to be handled by the caller function (like viewData), you should either avoid catching them in fetchData or rethrow them after catching:
As you can see, the same error object is caught in both functions because we rethrow it from fetchData to viewData.
Related Topics
To go further with the Fetch API, explore these related chapters:
- JavaScript Promise — the foundation Fetch is built on.
- Async/Await — the cleanest way to write Fetch calls.
- Fetch: Abort — cancel a request with
AbortController(useful for timeouts and search-as-you-type). - Fetch: Cross-Origin Requests — how CORS controls requests to other domains.
Conclusion
The Fetch API is an indispensable tool for JavaScript developers, enhancing web applications with its promise-based approach to network requests. Through practical examples, this guide demonstrates how the Fetch API can be effectively utilized for fetching data, handling errors, and making POST requests, leveraging the JSONPlaceholder API for real-world applications. Mastering the Fetch API empowers developers to create more responsive, dynamic, and robust web applications.