Fetch vs Axios. Hangisini tercih etmeli?

Zafer Ayan
5 min readFeb 23, 2023
Pikachu vs Raichu karşılaşmasından bir kare: https://www.youtube.com/watch?v=u8vgTX5ASQA

İngilizcesi için: https://zaferayan.medium.com/fetch-vs-axios-which-one-to-choose-e76872062820

Fetch ve Axios tartışmaları yıllardır olduğu gibi son zamanlarda da yine ortaya çıktı. Axios gibi bir network kütüphanesi kullanmak yerine Fetch API’ı direkt kullanmanın neden dezavantajlı olduğundan bahsedeceğim. Öncelikle Fetch API’daki eksiklikleri belirtelim:

TLDR:

  1. Response’u JSON’a çevirmek için ayrıca dönüştürmek gerekiyor
  2. POST, DELETE gibi isteklerde fetch içerisindeki options parametresine object geçirerek belirtmek gerekiyor
  3. 404, 500 gibi hata dönen status kodlarında reject etmediği için harici kontrol sağlamak gerekiyor
  4. Interceptor gibi yapılar sunmadığı için axios gibi kütüphaneleri yeniden keşfediyoruz
  5. Fetch API’ı encapsulate edip kendi mimarini oluşturmak gerekiyor
  6. Fetch çok generic ve get() post() gibi harici API’lara ihtiyaç var.

1. JSON convert işlemi

Client-Server iletişimi genellikle JSON data üzerinden gerçekleşiyor. Image: https://www.numpyninja.com/post/rest-request

Backend ile iletişim halihazırda REST API’larla ve JSON veri formatında gerçekleştiriliyor. Durum böyle iken gündelik kullandığımız API’ların da hızlı bir şekilde veriyi getirmesini bekleriz. Öncelikle fetch API’ın bu durumu nasıl çözdüğüne bakalım:

fetch('http://api.example.com/movies')
.then((response) => response.json())
.then((data) => console.log(data));

GET isteği yukarıdaki gibi fetch metodunun içerisine yazılan bir URL ile sağlanıyor. Devamında Response objesi dönüyor. Response içerisinde herhangi bir response formatını sunabildiği için genel kullanımda JSON’a convert etmek gerekiyor.

Axios tarafında nasıl hallediliyor bir de ona bakalım:

axios.get("http://api.example.com/movies")
.then((data) => console.log(data));

Üstte de görüldüğü gibi axios, genel kullanıma uygun bir format sunmuş ve varsayılan olarak JSON data içeriğini elde edebiliyorsunuz. Oldukça basit ve sade bir kullanıma sahip.

Kişisel görüşüm:
REST API kullanırken pek çok işlem JSON döndürdüğü için bu durumun fazla generic olduğunu düşünüyorum. Farklı tipteki response türleri opsiyonel olarak handle edilebilirdi. Örneğin axios’ta blob image dönen bir response’u şu şekilde kullanabiliyorsunuz:

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. POST gibi isteklerde parametre olarak ayrıca object geçmek gerekiyor

Fetch API syntax’ında resource (URL) haricinde bir de options parametresi bulunuyor. Kaynak: https://developer.mozilla.org/en-US/docs/Web/API/fetch#syntax

Bir form verisi veya herhangi bir JSON verisi ile DB’ye kayıt senaryosunu düşünelim. Fetch API ile post işlemi şu şekilde gerçekleşiyor.

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);
});

Fetch’in sunduğu API’da URL sonrasında options nesnesi içerisinde istekle ilgili diğer harici parametreler geçilebiliyor. Burada özellikle bir JSON datayı tekrar stringify() ederek sunucuya iletme işlemi her ne kadar generic bir yapı sunsa da, geliştirici açısından bir külfet niteliğinde.

Şimdi aynı isteğin axios tarafında nasıl yapıldığına bakalım:

axios.post("http://api.example.com/movies", {
title: "The Lord of the Rings",
rating: 5,
})
.then(function (data) {
console.log("Success:", data);
});

Üstte de görüldüğü gibi, Fetch API tarafında 14 satır olan kodu 7 satır kodla daha sade bir biçimde gerçekleştirebilir. Axios’un kendi API’si varsayılan olarak genel kullanıma yönelik olduğu için en basit şekilde çözüme götürecek şekilde tasarlanmış.

3. 404, 500 gibi hata kodlarında reject mekanizması bulunmuyor

Image: https://http.cat/404

Fetch API hata durumunu yalnızca network taraflı bir sorun olduğunda handle ediyor. Sunucu tarafından ilgili id’ye bağlı kaydın bulunmaması gibi 404 durumlarında, http status kodlarını harici olarak handle etmek gerekiyor.

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);
});

response.ok değişkeni, HTTP status kodunun 200–299 aralığında gelmesi durumunda true döndürüyor. Aksi halde throw ederek catch bloğuna düşürmek gerekli.

Şimdi de axios tarafında nasıl handle ediyoruz yakından bakalım:

axios.get("http://api.example.com/movies/1")
.then((data) => console.log(data))
.catch(function (error) {
console.error(error);
});

Burada da görüldüğü gibi axios, 400–500 durumlarında varsayılan olarak hata fırlatacak şekilde tasarlanmış. Bu nedenle harici olarak throw işlemine gerek kalmadan handle edebiliyorsunuz.

Ek olarak, 400–500 hata kodlarında exception fırlatmasını engellemek için aşağıdaki gibi validateStatus parametresini override edebilirsiniz (varsayılan değeri true):

axios.get(url, { validateStatus: false })

4. Interceptor sunmuyor

Interceptorler request ve response’ları modifiye ederek HTTP isteklerinin şifrelenerek gönderilmesi gibi görevlerde önemli rol oynar.

Interceptor kelimesi, network alanında kullandığımızda ağ isteklerinin arasına girerek yapılan işlemler olarak tanımlayabiliriz. Onur Dayıbaşı bir yazısında Interceptor kullanım alanlarına şu şekilde değinmiş:

  1. Log: Network isteklerinin ve cevaplarının kayıtları tutulabilir.
  2. Authentication: Her istekte belirli bir token/key değeri sunucuya iletilebilir.
  3. Encryption: Güvenlik öncellikli uygulamalarda istekler client-side’da şifrelenip sunucuya iletilebilir.
  4. Error handling: Herhangi bir hata gelmesi durumunda farklı sayfalara redirect işlemi yapılabilir.

Interceptor kullanımı ne kadar gereksiz gibi görünse de, uygulama karmaşıklaştıkça önemi daha çok anlaşılır hale geliyor.

Axios tarafında bir interceptor aşağıdaki gibi axios objesi ile kullanılabilir:

// 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’ı encapsulate ederek mimari oluşturmak gerekiyor.

BASE_URL, timeout, custom headers gibi uygulamaya özgü parametreleri ayrı ayrı tüm isteklere vermek için Fetch’i sarmalayarak bu değişkenleri harici olarak vermek gerekiyor. Bu sorun da beraberinde “fetch API’ı nasıl generic kullanacağız?” sorusunu oluşturuyor.

Axios’ta ise axios instance’ı oluşturup kolaylıkla kullanılabilir:

const instance = axios.create({
baseURL: 'https://api.example.com',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});

6. Fetch çok generic

fetch kelimesi bir şeyleri getirmeyi çağrıştırdığı için POST gibi işlemlerde fetch kullanmak kelime anlamının dışına çıkmış oluyor. Özellikle eğitim içeriği sunuyorsanız fetch kelimesi üzerinden bir POST işleminden bahsetmek dahi anlamsız olabiliyor.

Bu noktada aynı axios ve jquery gibi network isteği yapan kütüphanelerdeki gibi get(), post(), delete() gibi API’lara ihtiyaç var.

Axios’un sunduğu alias’lar:

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]])

Axios gibi harici network kütüphanelerinin boyutu

Eğer fetch API yerine harici bir network kütüphanesi kullanmak isterseniz, bundle size’a doğrudan etki ediyor ve sayfanın açılma süresini bir miktar arttırıyor.

Bundlephobia sitesinde Axios kütüphanesinin boyutu ve indirme hızları aşağıdaki gibi listeleniyor:

Axios kütüphanesinin boyutu ve farklı network tiplerinde indirme hızları

Axios’a nazaran daha küçük boyutlu (2kb) fetch wrapper kütüphaneleri kullanmak da mümkün: https://github.com/elbywan/wretch

Sonuç olarak

Axios gibi kütüphanelerin rahatlıkla çözebildiği sorunlar fetch API özel bir şekilde sarmalanarak çözülebilir. Ancak bu durumda da kütüphanenin yeniden keşfedilmesi durumu oluşuyor.

Kişisel görüşüm, eğer bundle size konusunda büyük bir endişeniz yoksa gündelik kodlama süreçlerinde axios kullanabilirsiniz.

Bu yazımda eksik/hatalı olduğunu düşündüğünüz kısımlar varsa bana ulaşabilirsiniz. Sonraki yazımda tekrargörüşmek üzere…

--

--