Frontend'de Axios ile API tüketmek
Axios kütüphanesiyle istek/yanıt katmanını arayüzde temiz tutmak için interceptor, hata yönetimi ve ortak yapılandırma üzerine pratik notlar.
Vue projelerinde API isteklerini ele almak için bir süre ham fetch API’sini kullandım. Çalışıyor, tarayıcıya dahil, ekstra bağımlılık yok. Ama her istekte aynı başlıkları tekrar yazmak, JSON parse etmeyi elle yapmak ve hataları her yerde ayrı ayrı ele almak kodu gereksiz yere şişiriyordu. Axios’a geçtikten sonra bu tekrarlar ortadan kalktı.
Axios nedir?
Axios, Promise tabanlı bir HTTP istemcisidir. Tarayıcıda XMLHttpRequest, Node.js tarafında http modülü üzerine inşa edilmiş; her iki ortamda da aynı arayüzle çalışıyor. Otomatik JSON dönüşümü, istek iptali ve interceptor desteği gibi özellikleri ham fetch API’sinin üstüne koyuyor.
Kurulumu basit:
npm install axios
Temel kullanım
import axios from 'axios'
// GET isteği
axios.get('/api/users')
.then(response => {
console.log(response.data)
})
.catch(error => {
console.error(error)
})
// POST isteği
axios.post('/api/users', {
name: 'Muhammet',
email: '[email protected]'
})
.then(response => console.log(response.data))
response.data doğrudan JSON nesnesine erişimi sağlıyor; elle .json() çağırmak gerekmiyor. Bu küçük ama sürekli kullanıldığında hissedilen bir rahatlama.
Ortak yapılandırma: axios instance
Her istekte temel URL’yi, yetkilendirme başlığını tekrar yazmamak için özelleştirilmiş bir Axios instance’ı oluşturmak iyi bir alışkanlık:
// src/api/client.js
import axios from 'axios'
const apiClient = axios.create({
baseURL: process.env.VUE_APP_API_URL || '/api',
timeout: 10000,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
}
})
export default apiClient
Artık tüm isteklerde bu apiClient’ı içe aktarıyorsunuz; /api öneki, başlıklar ve timeout otomatik geliyor.
Interceptor ile merkezi işlem
Interceptor, istek gönderilmeden önce ya da yanıt alındıktan sonra devreye giren bir ara işlemdir. Yetkilendirme token’ını eklemek ya da hataları merkezi olarak yakalamak için idealdir.
İstek interceptor’u örneği:
apiClient.interceptors.request.use(
config => {
const token = localStorage.getItem('auth_token')
if (token) {
config.headers['Authorization'] = `Bearer ${token}`
}
return config
},
error => Promise.reject(error)
)
Her istek bu interceptor’dan geçtiği için token eklemeyi her istek noktasında tekrar yazmak gerekmiyor.
Yanıt interceptor’u örneği — 401 durumunda oturumu sonlandırmak:
apiClient.interceptors.response.use(
response => response,
error => {
if (error.response && error.response.status === 401) {
// Token geçersiz; oturum temizle, giriş sayfasına yönlendir
localStorage.removeItem('auth_token')
window.location.href = '/login'
}
return Promise.reject(error)
}
)
Bu iki interceptor ile yetkilendirme ve oturum yönetiminin merkezi noktası tek bir dosyada toplandı.
İstek modüllerini ayırmak
Axios instance’ı hazır; sonraki adım API çağrılarını bileşenlerden ayırmak. Her kaynak için ayrı bir modül yazmak bu işi temizleştiriyor:
// src/api/users.js
import apiClient from './client'
export const getUsers = () => apiClient.get('/users')
export const getUser = (id) => apiClient.get(`/users/${id}`)
export const createUser = (data) => apiClient.post('/users', data)
export const updateUser = (id, data) => apiClient.put(`/users/${id}`, data)
export const deleteUser = (id) => apiClient.delete(`/users/${id}`)
Vue bileşeninde kullanım:
import { getUsers } from '@/api/users'
export default {
data() {
return { users: [] }
},
async created() {
try {
const response = await getUsers()
this.users = response.data
} catch (error) {
console.error('Kullanıcılar yüklenemedi', error)
}
}
}
Bileşen, Axios’tan haberdar değil. Sadece getUsers fonksiyonunu çağırıyor. API’nin hangi kütüphaneyle tüketildiğini değiştirmeniz gerekirse yalnızca src/api/users.js değişiyor.
Hata durumlarını ele almak
Axios, HTTP hata durumlarında (4xx, 5xx) otomatik olarak Promise’i reddediyor. catch bloğunda error.response varlığını kontrol ederek sunucu hatası mı, ağ hatası mı olduğunu ayırt edebilirsiniz:
try {
await createUser(data)
} catch (error) {
if (error.response) {
// Sunucu yanıt verdi ama 2xx dışı bir durum kodu döndürdü
console.error('Sunucu hatası:', error.response.status)
} else if (error.request) {
// İstek gönderildi ama yanıt alınamadı (ağ sorunu)
console.error('Ağ hatası')
} else {
// İstek oluşturulurken hata oluştu
console.error('İstek hatası:', error.message)
}
}
fetch ile karşılaştırma
Ham fetch kullananlar için bir not: fetch, 4xx ve 5xx yanıtlarda Promise’i reddetmez — response.ok kontrolünü kendiniz yapmak gerekir. Axios bu davranışı tersine çevirdiği için hata yönetimi catch’e konsolide oluyor. Hangi yaklaşımı tercih edeceğiniz kişisel tercih meselesi, ama interceptor’lara ve otomatik JSON dönüşümüne ihtiyacınız varsa Axios bir adım öne çıkıyor. Ekstra bağımlılık eklemek istemiyorsanız ve basit bir proje söz konusuysa fetch de yeterli.
Sonuç
Axios’u doğrudan bileşenlere gömmek yerine ayrı bir API katmanı olarak yapılandırmak, frontend kodunu bakımı kolay tutuyor. Interceptor’lar merkezi işlemleri tek yere topluyor; modüler yapı ise bileşenleri HTTP kütüphanesinden bağımsız kılıyor. Bu katmanı oturtmak başlangıçta birkaç ekstra dosya demek ama proje büyüdükçe bu yatırım değerini gösteriyor.
Son olarak bir tuzak: interceptor zincirinde unhandled rejection bırakmak sorun çıkarabiliyor. Yanıt interceptor’unda return Promise.reject(error) yazmayı unutursanız, hata yutulmuş oluyor ve bileşendeki catch bloğu hiç tetiklenmiyor. Özellikle 401 yönlendirmesi eklenirken bu satırın eksik kalması, kullanıcıyı giriş sayfasına yönlendiriyor ama bileşenin hata durumunu işlememesine neden oluyor. Interceptor yazarken her kod yolunun bir değer ya da reddedilmiş Promise döndürdüğünden emin olmak önemli.