Fetch API
The Fetch API provides a JavaScript interface for making HTTP requests and processing the responses.
Fetch API is the modern replacement for XMLHttpRequest API: unlike XMLHttpRequest, which uses callbacks, Fetch is promise-based and is integrated with features of the modern web such as service workers and Cross-Origin Resource Sharing (CORS).
Using the Fetch API Steps
- Make a request by calling
fetch()
. - pass it a
Request
object or a string containing the URL to fetch, along with an optional argument to configure the request. - The
fetch()
function returns aPromise
which is fulfilled with aResponse
object representing the server’s response. - You can then check the request status and extract the body of the response in various formats, including text and JSON, by calling the appropriate method on the response.
The minimal example:
async function getData() {
const url = "https://example.org/products.json";
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Response status: ${response.status}`);
}
const json = await response.json();
console.log(json);
} catch (error) {
console.error(error.message);
}
}
Making a request
Setting a body
The request body is the payload of the request: it’s the thing the client is sending to the server. You don’t need a body with GET
requests, but it’s useful for requests that send content to the server, such as POST
or PUT
requests.
const response = await fetch("https://example.org/post", {
method: "POST",
body: JSON.stringify({ username: "example" }),
// ...
});
body
can be a string or ArrayBuffer, TypedArray etc.
Setting headers
Request headers give the server information about the request: for example, the Content-Type
header tells the server the format of the request’s body. You can pass an object literal here containing header-name: header-value
properties.
const response = await fetch("https://example.org/post", {
headers: {
"Content-Type": "application/json",
'X-Shopify-Storefront-Access-Token': 'key-eikdjsa;je;fmdjasiopej4f4t3g324r4',
},
// .,.
});
Making cross-origin requests
mode
option, three values: cors, no-cors, or same-origin.
By default, mode
is set to cors
, meaning that if the request is cross-origin then it will use the Cross-Origin Resource Sharing (CORS) mechanism. There are two kinds requests:
- simple request: the request will always be sent, but the server must respond with the correct
Access-Control-Allow-Origin
header or the browser will not share the response with the caller. - preflighted request: browser will send a preflighted request to check that the server understands CORS and allows the request, and the real request will not be sent unless the server responds to the preflighted request with the appropriate CORS headers.
Setting mode
to same-origin
disallows cross-origin requests completely. Setting mode
to no-cors
means the request must be a simple request, which restricts the headers that may be set, and restricts methods to GET, HEAD, and POST.
Reading response
Request and response bodies are actually ReadableStream
objects, and whenever you read them, you’re streaming the content. This is good for memory efficiency, because the browser doesn’t have to buffer the entire response in memory before the caller retrieves it using a method like json()
.
response.json()
Return value: A Promise that resolves to a JavaScript object. This object could be anything that can be represented by JSON — an object, an array, a string, a number…
Other Reading the response body methods:
Response.arrayBuffer()
Response.blob()
Response.formData()
Response.json()
Response.text()
You can read status, type, headers as well.
Understand request
and response
object
request
and response
objects are all work around with fetch
function.
request
object is what you want from fetch
. response
object is what you get from fetch
.
Request and response bodies are actually ReadableStream
objects, and whenever you read them, you’re streaming the content.
Fetch vs Axios
What is Axios
Axios is a third-party library, a promise-based third-party HTTP client library for the browser and Node.js. It provides an easy-to-use API and offers features such as making asynchronous requests, handling request and response interception, and automatic transformation of JSON data.
Sending a GET Request with Query Parameters:
// Axios
axios.get('/api/data', {
params: {
name: 'Alice',
age: 25
}
})
.then(response => {
// handle response
})
.catch(error => {
// handle error
});
// Fetch
const url = new URL('/api/data');
url.searchParams.append('name', 'Alice');
url.searchParams.append('age', 25);
fetch(url)
.then(response => response.json())
.then(data => {
// handle data
})
.catch(error => {
// handle error
});
Sending a POST Request with a JSON Body
// Axios
axios.post('/api/data', {
name: 'Bob',
age: 30
})
.then(response => {
// handle response
})
.catch(error => {
// handle error
});
// Fetch
fetch('/api/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Bob',
age: 30
})
})
.then(response => response.json())
.then(data => {
// handle data
})
.catch(error => {
// handle error
});
Setting a Timeout for the Request:
// Axios
axios.get('/api/data', {
timeout: 5000 // 5 seconds
})
.then(response => {
// handle response
})
.catch(error => {
// handle error
});
// Fetch
const controller = new AbortController();
const signal = controller.signal;
setTimeout(() => {
controller.abort(); // abort after 5 seconds
}, 5000);
fetch('/api/data', { signal })
.then(response => response.json())
.then(data => {
// handle data
})
.catch(error => {
// handle error
});
Error Handling
Axios:
In Axios, if there is a request failure, it throws an error and you can easily handle the error with a try-catch block and get the error data from error.response.data
. For example:
// Axios error handling with try-catch
try {
const response = await axios.get('/api/data');
// handle response
} catch (error) {
// handle error
console.log(error.response.data);
}
Fetch:
In Fetch, if there is a request failure, it does not throw an error, but returns a response object with an ok property set to false. You have to check the ok property and throw an error manually if you want to use a try-catch block.
Alternatively, you can use the response.ok property to handle different cases in the then method. For example:
// Fetch error handling with try-catch
try {
const response = await fetch('/api/data');
// check response status
if (!response.ok) {
// throw error if status is not ok
throw new Error(`HTTP error! status: ${response.status}`);
}
// handle response
} catch (error) {
// handle error
console.log(error.message);
}
// Fetch error handling with response.ok
fetch('/api/data')
.then(response => {
// check response status
if (response.ok) {
// handle response
} else {
// handle error
console.log(`HTTP error! status: ${response.status}`);
}
})
.catch(error => {
// handle network error
console.log(error.message);
});
Using async/await syntax:
// Axios
async function getData() {
try {
const response = await axios.get('/api/data');
// handle response
} catch (error) {
// handle error
}
}
// Fetch
async function getData() {
try {
const response = await fetch('/api/data');
const data = await response.json();
// handle data
} catch (error) {
// handle error
}
}
Compatibility
Axios:
- Axios is a third-party library that needs to be installed and included in your project.
- It supports older browsers by including polyfills for promises and other modern JavaScript features.
- Axios is actively maintained and keeps up with the latest browser and Node.js updates, ensuring compatibility with new environments.
- However, since it’s a separate library, you need to ensure that you’re using a compatible version with your project dependencies.
Fetch:
- The Fetch API is a native Web API supported by modern browsers.
- It has excellent support in recent browser versions, but older browsers (such as Internet Explorer) do not support it natively.
- If you need to support older browsers, you’ll need to include a polyfill or use a fallback solution (e.g., XMLHttpRequest).
- Since it’s a native API, it’s automatically updated and maintained by browser vendors, ensuring compatibility with future browser versions.
handle non-200 status codes
Another difference between Fetch and Axios is how they handle non-200 status codes. Axios considers any status code outside the range of 2xx as an error and rejects the promise. Fetch considers any valid HTTP response (even 4xx or 5xx) as a success and resolves the promise. This means that you have to handle non-200 status codes differently in Fetch and Axios.
Next.js extends fetch
Fetching Data on the Server with fetch
Next.js extends the native fetch
Web API to allow you to configure the caching and revalidating behavior for each fetch request on the server. So you don’t need to worry fetch data many time or in many places.
React extends fetch
to automatically memoize fetch requests while rendering a React component tree.
You can use fetch
with async/await
in Server Components, in Route Handlers, and in Server Actions.