The Fetch vs Axios debate has been going on for years and recently it has come up again. I will talk about the disadvantages of using the Fetch API directly instead of using a network library like Axios. First of all, let’s point out the shortcomings of the Fetch API:
TLDR:
- To convert Response to JSON you also need to convert.
- In requests such as POST, DELETE, it is necessary to specify by passing object to the options parameter in fetch.
- In status codes returning errors such as 404, 500, it is necessary to provide external control because it does not reject.
- We rediscover libraries like axios because it doesn’t offer structures like Interceptor.
- Need to encapsulate Fetch API and create your own architecture.
- Fetch is too generic and needs external APIs like get() post().
• • •
1. JSON convert operation
Client-Server communication usually takes place over JSON data.
Communication with the backend is currently done with REST APIs and in JSON data format. In this case, we expect the APIs we use daily to fetch data quickly. Let’s first look at how the fetch API solves this situation:
fetch('http://api.example.com/movies')
.then((response) => response.json())
.then((data) => console.log(data));
GET request is generated with a URL written in the fetch method as above. Then the Response object is returned. Since Response can provide any response format in Response, it is necessary to convert it to JSON in general use.
Let’s see how it is handled on the Axios side:
axios.get("http://api.example.com/movies")
.then((data) => console.log(data));
As you can see above, axios has provided a generic format and by default you can get JSON data content. It’s quite simple and straightforward.
Personal opinion: I think this Fetch API is too generic since many operations return JSON when using REST API. Different types of response types could be handled optionally. For example, in axios, you can use a response that returns a blob image as follows:
axios.get(imageUrl, { responseType: "blob" })
.then(function (response) {
var reader = new window.FileReader();
reader.readAsDataURL(response.data);
reader.onload = function () {
var imageDataUrl = reader.result;
imageElement.setAttribute("src", imageDataUrl);
};
});
2. For requests such as POST, it is also necessary to pass object as a parameter
Fetch API syntax has an options parameter in addition to resource (URL).
Let’s consider the scenario of saving new movie to database with a form data or any JSON data. The post operation with Fetch API is as follows:
fetch("http://api.example.com/movies", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: "The Lord of the Rings",
rating: 5,
}),
})
.then((response) => response.json())
.then((data) => {
console.log("Success:", data);
});
In the API offered by Fetch, other external parameters related to the request can be passed in the options object after the URL. Here, especially the process of passing a JSON data to the server by stringify() again is a burden for the developer, even though it offers a generic structure.
Now let’s see how the same request is done on the axios side:
axios.post("http://api.example.com/movies", {
title: "The Lord of the Rings",
rating: 5,
})
.then(function (data) {
console.log("Success:", data);
});
As you can see above with fetch API, you can implement the 14 lines of code. In the other way axios do with it just 7 lines of code. Since Axios’ own API is for general use by default, it is designed to lead to the simplest solution.
3. HTTP error codes such as 404, 500 do not throw any error
Fetch API handles the error only when there is a network-side issue. In 404 cases, such as the absence of a record associated with the relevant id by the server, it is necessary to handle the http status codes manually:
fetch("http://api.example.com/movies/1")
.then((response) => {
if (response.ok) {
return response.json();
}
throw new Error("404: Not Found");
})
.then((data) => {
console.log(data);
})
.catch((error) => {
console.error(error);
});
The response.ok variable returns true if the HTTP status code is in the range of 200–299. Otherwise, it is necessary to throw error to handle in block.
Now let’s take a closer look at how we handle it on the axios side:
axios.get("http://api.example.com/movies/1")
.then((data) => console.log(data))
.catch(function (error) {
console.error(error);
});
As you can see here, axios is designed to throw errors by default at 400–500 cases. Therefore, you can handle it without the need for a throw.
Additionally, to avoid throwing exceptions on error codes 400–500, you can override the validateStatus parameter as follows (defaults to true):
axios.get(url, { validateStatus: false })
4. Interceptor issue
Interceptors play an important role in tasks such as sending encrypted HTTP requests by modifying requests and responses.
When we use theInterceptor term in the network concept, we can define it as the operations performed such as modifying network requests and responses. Onur Dayıbaşı mentioned interceptor and use cases in one of his articles as follows:
- Logging: Logging of network requests and responses
- Authentication: A specific token/key value can be transmitted to the server with each request.
- Encryption: In security-focused applications, requests/responses can be encrypted/decrypted on the client-side.
- Error handling: In case of any error, redirect to different pages can be done with interceptors.
No matter how unnecessary the use of the Interceptor may seem, its importance becomes clearer as the application becomes more complex.
On the axios side, an interceptor can be used with the axios object as follows:
// Request interceptor
axios.interceptors.request.use(
function (config) {
// Do something before request is sent
return config;
},
function (error) {
// Do something with request error
return Promise.reject(error);
}
);
// Response interceptor
axios.interceptors.response.use(
function (response) {
// 2xx responses
// Do something with response data
return response;
},
function (error) {
// 4xx, 5xx responses
// Do something with response error
return Promise.reject(error);
}
);
5. Fetch API needs to wrapping for generic use
In order to give application-specific parameters such as BASE_URL, timeout, custom headers to all requests separately, it is necessary to export these variables by wrapping Fetch. This problem is accompanied by the question “How do we use the fetch API generic?” poses the question.
const instance = axios.create({
baseURL: 'https://api.example.com',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
6. Fetch çok generic
Since the word fetch connotes fetching something, using fetch in operations such as POST goes beyond the meaning of the word. Especially if you are providing educational content, even talking about a POST operation over the word fetch can be meaningless.
At this point, APIs such as get(), post(), delete() are needed, just like in libraries that make network requests such as axios and jquery.
The aliases offered by Axios are:
axios.request(config)
axios.get(url[, config])
axios.delete(url[, config])
axios.head(url[, config])
axios.options(url[, config])
axios.post(url[, data[, config]])
axios.put(url[, data[, config]])
axios.patch(url[, data[, config]])
axios.postForm(url[, data[, config]])
axios.putForm(url[, data[, config]])
axios.patchForm(url[, data[, config]])
External network libraries such as Axios negatively affect application size
If you want to use an external network library instead of the fetch API, adding a library directly affects the application size and increases the page opening time a little.
The size and download speeds of the Axios library are listed on the Bundlephobia site as follows:
Size of Axios library and download speeds on different network types.
It is also possible to use smaller (2kb) fetch wrapper libraries compared to Axios: https://github.com/elbywan/wretch
In conclusion
Problems that libraries like Axios can easily solve can be solved by wrapping the fetch API in a customized way. However, in this cases, axios like network libraries are rediscovered again.
IMHO you can use axios in your daily development if you don’t have a big concern about the bundle size.