Fetch API’ye Giriş: Modern Web İstekleri İçin Temel Rehber
Web uygulamaları geliştirirken, sunucu ile veri alışverişi yapmak kaçınılmaz bir ihtiyaçtır. Kullanıcı verilerini kaydetmek, API’lardan bilgi çekmek veya dosya yüklemek gibi işlemler, arka planda HTTP istekleri aracılığıyla gerçekleşir. Geleneksel olarak bu tür işlemler için XMLHttpRequest (XHR) API’ı kullanılırdı. Ancak modern JavaScript dünyasında, daha güçlü, esnek ve kullanımı kolay bir alternatif öne çıkmaktadır: Fetch API.
Fetch API, web tarayıcılarında ve Node.js gibi çalışma zamanlarında HTTP istekleri yapmanızı sağlayan, Promise tabanlı modern bir arayüzdür. XHR’ın karmaşık geri çağırma (callback) zincirleri yerine, Promise’lerin sunduğu zincirleme (.then(), .catch(), .finally()) yapısıyla asenkron işlemleri çok daha okunaklı ve yönetilebilir hale getirir. Bu rehberde, Fetch API’nin temel kullanımından gelişmiş özelliklerine, pratik ipuçlarından sıkça sorulan sorulara kadar her şeyi ele alacağız.
Fetch API’nin Temelleri: İlk İsteklerinizi Yapın
Fetch API’nin en temel kullanımı, bir URL’ye GET isteği göndermektir. Bu işlem, sadece bir fonksiyon çağrısı ile başlar ve bir Promise döndürür. Bu Promise, isteğin başarılı olup olmadığına veya bir hata oluşup oluşmadığına dair bilgi taşır.
Basit Bir GET İsteği
Aşağıdaki örnek, bir API’dan kullanıcı verilerini nasıl çekeceğinizi göstermektedir. İstek başarılı olduğunda, yanıtı JSON formatına dönüştürüp konsola yazdırırız.
fetch('https://jsonplaceholder.typicode.com/users')
.then(response => {
// HTTP yanıtının başarılı (2xx) olup olmadığını kontrol edin
if (!response.ok) {
throw new Error(HTTP hata kodu: ${response.status});
}
// Yanıtı JSON olarak ayrıştırın
return response.json();
})
.then(data => {
// Ayrıştırılmış JSON verisini kullanın
console.log('Kullanıcı Verileri:', data);
})
.catch(error => {
// Ağ hatalarını veya yukarıdaki throw edilen hataları yakalayın
console.error('Fetch işlemi sırasında bir hata oluştu:', error);
});
Yukarıdaki kodda dikkat etmeniz gereken birkaç önemli nokta var:
fetch('URL'): Bu, belirtilen URL’ye bir GET isteği gönderir ve bir Promise döndürür..then(response => ...): İlk.then()bloğu, sunucudan bir yanıt (Responsenesnesi) alındığında çalışır. Bu aşamada ağ hatası oluşmamıştır, ancak HTTP durum kodu (örn. 404 Not Found, 500 Internal Server Error) hala bir hata durumunu gösterebilir. Bu nedenleresponse.okkontrolü önemlidir.response.ok: Bu özellik, HTTP yanıtının başarılı bir durum kodu (200-299 aralığında) olup olmadığını gösteren bir boolean değeridir.response.json(): Bu, yanıt gövdesini JSON olarak ayrıştıran ve başka bir Promise döndüren bir metottur. Bu Promise, ayrıştırılmış JSON verisiyle çözümlenir. Benzer şekilderesponse.text(),response.blob(),response.arrayBuffer()gibi metotlar da mevcuttur..then(data => ...): İkinci.then()bloğu, JSON verisi başarıyla ayrıştırıldığında çalışır..catch(error => ...): Bu blok, Fetch işlemi sırasında herhangi bir ağ hatası (örn. bağlantı kesilmesi) veya Promise zincirinde fırlatılan bir hata (örn.throw new Error(...)) oluştuğunda çalışır.
HTTP Metodları ve İstek Seçenekleri
Fetch API, sadece GET istekleri yapmakla kalmaz, aynı zamanda POST, PUT, DELETE gibi diğer HTTP metodlarını da destekler. Bu metodları ve isteğinizle ilgili diğer detayları (başlıklar, gövde vb.) belirtmek için fetch() fonksiyonunun ikinci parametresi olan bir seçenekler nesnesini (RequestInit) kullanırız.
POST İsteği ve İstek Seçenekleri
Bir sunucuya veri göndermek (örn. yeni bir kaynak oluşturmak) için POST metodunu kullanırız. Bu durumda, isteğin gövdesinde (body) gönderilecek veriyi ve Content-Type başlığını belirtmemiz gerekir.
const newUser = {
name: 'Ayşe Yılmaz',
username: 'ayseyilmaz',
email: 'ayse.yilmaz@example.com'
};
fetch('https://jsonplaceholder.typicode.com/users', {
method: 'POST', // HTTP metodu
headers: {
'Content-Type': 'application/json' // Gönderilen verinin tipi
},
body: JSON.stringify(newUser) // JS nesnesini JSON string'ine dönüştür
})
.then(response => {
if (!response.ok) {
throw new Error(HTTP hata kodu: ${response.status});
}
return response.json();
})
.then(data => {
console.log('Yeni Kullanıcı Oluşturuldu:', data);
})
.catch(error => {
console.error('Kullanıcı oluşturulurken bir hata oluştu:', error);
});
Yukarıdaki örnekte kullanılan önemli seçenekler:
method: İstekte kullanılacak HTTP metodunu belirtir (GET, POST, PUT, DELETE vb.). Varsayılan değer GET’tir.headers: İstek başlıklarını içeren bir nesnedir. ÖzellikleContent-Type, sunucuya gönderilen verinin formatını bildirir.Authorizationbaşlığı, kimlik doğrulama token’larını göndermek için sıkça kullanılır.body: İstek gövdesinde gönderilecek veriyi içerir. POST veya PUT gibi metodlar için gereklidir. Genellikle bir JavaScript nesnesiniJSON.stringify()ile JSON string’ine dönüştürerek göndeririz.
Diğer Sık Kullanılan Seçenekler
mode: İstek modunu belirtir ('cors','no-cors','same-origin'). Çoğu zaman varsayılan'cors'yeterlidir.cache: İstek için önbellek davranışını belirler ('default','no-cache','reload'vb.).credentials: Çerezlerin, HTTP kimlik doğrulama başlıklarının veya istemci SSL sertifikalarının isteklerle birlikte gönderilip gönderilmeyeceğini belirler ('omit','same-origin','include'). Genellikle'include', kimlik doğrulaması gereken API’lar için kullanılır.
Gelişmiş Kullanım: Async/Await ve Hata Yönetimi
Promise’ler güçlü olsa da, karmaşık asenkron akışlarda .then() zincirleri hala iç içe geçebilir. ES2017 ile tanıtılan async/await sözdizimi, Promise tabanlı kodları senkron koda benzer şekilde yazmamızı sağlayarak, Fetch API ile çalışmayı daha da kolaylaştırır ve okunaklı hale getirir.
Async/Await ile Fetch Kullanımı
Aynı kullanıcı çekme örneğini async/await ile yeniden yazalım:
async function fetchUsers() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
if (!response.ok) {
throw new Error(HTTP hata kodu: ${response.status});
}
const data = await response.json();
console.log('Kullanıcı Verileri (Async/Await):', data);
} catch (error) {
console.error('Kullanıcılar getirilirken bir hata oluştu:', error);
}
}
fetchUsers();
Bu yaklaşım, özellikle birden fazla asenkron adım içeren işlemlerde kodun akışını takip etmeyi çok daha kolaylaştırır. await anahtar kelimesi, Promise’in çözümlenmesini bekler ve çözümlenen değeri döndürür. Eğer Promise reddedilirse, hata try...catch bloğu tarafından yakalanır.
İstek İptali (AbortController)
Bazen bir Fetch isteğini, kullanıcı başka bir sayfaya geçtiğinde veya daha yeni bir istek yapıldığında iptal etmek isteyebiliriz. Fetch API, bu senaryo için AbortController arayüzünü sunar.
const controller = new AbortController();
const signal = controller.signal;
async function fetchWithCancellation() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts/1', { signal });
if (!response.ok) {
throw new Error(HTTP hata kodu: ${response.status});
}
const data = await response.json();
console.log('Veri alındı:', data);
} catch (error) {
if (error.name === 'AbortError') {
console.log('Fetch isteği iptal edildi.');
} else {
console.error('Bir hata oluştu:', error);
}
}
}
fetchWithCancellation();
// Belirli bir süre sonra isteği iptal edin (örneğin 2 saniye sonra)
setTimeout(() => {
controller.abort();
}, 2000);
AbortController bir sinyal (signal) sağlar ve bu sinyali fetch() fonksiyonuna seçenek olarak iletiriz. controller.abort() çağrıldığında, sinyali dinleyen Fetch isteği iptal edilir ve bir AbortError fırlatılır. Bu, istek zaman aşımı (timeout) yönetimi için de kullanılabilir.
Pratik İpuçları ve En İyi Yöntemler
Fetch API ile çalışırken karşılaşabileceğiniz bazı yaygın senaryolar ve bunları yönetmek için ipuçları:
CORS (Cross-Origin Resource Sharing)
Tarayıcılar, güvenlik nedeniyle farklı bir kaynaktan (domain, port veya protokol) yapılan isteklere kısıtlamalar getirir. Bu kısıtlamalara CORS politikası denir. Eğer bir API’dan veri çekerken tarayıcı konsolunda CORS hatası görüyorsanız, bu genellikle API sunucusunun sizin kaynağınızdan gelen isteklere izin vermediği anlamına gelir. Bu durumda, API geliştiricileriyle iletişime geçmeniz veya proxy sunucusu kullanmanız gerekebilir.
Kimlik Doğrulama (Authentication)
Birçok API, isteklerin kimlik doğrulaması yapılmasını gerektirir. Bu genellikle istek başlıklarına bir kimlik doğrulama token’ı (örneğin, JWT – JSON Web Token) ekleyerek yapılır:
const authToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'; // Token'ınızı buraya ekleyin
fetch('https://api.example.com/secure-data', {
method: 'GET',
headers: {
'Authorization': Bearer ${authToken} // Bearer şeması sıkça kullanılır
}
})
.then(response => response.json())
.then(data => console.log('Güvenli Veri:', data))
.catch(error => console.error('Kimlik doğrulama hatası:', error));
İstekleri Tekrar Kullanılabilir Hale Getirme
Sıkça kullanılan Fetch isteklerini veya belirli bir API’a yönelik istekleri bir yardımcı fonksiyonda sarmalamak, kodunuzu daha modüler ve okunabilir hale getirir.
async function apiRequest(url, options = {}) {
const defaultHeaders = {
'Content-Type': 'application/json',
'Authorization': Bearer ${localStorage.getItem('token')} // Token'ı Local Storage'dan al
};
const config = {
...options,
headers: {
...defaultHeaders,
...options.headers // Özel başlıklar varsayılanları ezebilir
}
};
const response = await fetch(url, config);
if (!response.ok) {
// Hata durumunda daha detaylı bilgi fırlatabiliriz
const errorData = await response.json().catch(() => ({ message: 'Bilinmeyen Hata' }));
throw new Error(${response.status}: ${errorData.message || response.statusText});
}
return response.json();
}
// Kullanımı:
apiRequest('https://api.example.com/users')
.then(users => console.log('Kullanıcılar:', users))
.catch(err => console.error('API isteği hatası:', err));
apiRequest('https://api.example.com/products', {
method: 'POST',
body: JSON.stringify({ name: 'Yeni Ürün', price: 100 })
})
.then(product => console.log('Ürün oluşturuldu:', product))
.catch(err => console.error('Ürün oluşturma hatası:', err));
Bu tür bir yardımcı fonksiyon, hata yönetimini merkezileştirmenize ve tekrar eden kodları azaltmanıza olanak tanır.
Sonuç ve Sıkça Sorulan Sorular (SSS)
Fetch API, modern web geliştirmenin vazgeçilmez bir parçasıdır. Promise tabanlı yapısı, async/await ile birleştiğinde, asenkron HTTP istekleri yapmayı hem güçlü hem de keyifli bir deneyim haline getirir. Ağ hatalarını, HTTP durum kodlarını ve istek iptalini yönetme yeteneği, sağlam ve kullanıcı dostu uygulamalar geliştirmenize yardımcı olur. Bu rehber, Fetch API’nin temel ve gelişmiş kullanımlarını anlamanız için sağlam bir zemin sağlamıştır.
Sıkça Sorulan Sorular (SSS)
- Fetch API nedir?
- Fetch API, web tarayıcılarında ve Node.js gibi JavaScript çalışma zamanlarında ağ istekleri (HTTP istekleri) yapmak için kullanılan modern, Promise tabanlı bir arayüzdür. Sunucu ile veri alışverişi yapmak için kullanılır.
- Fetch API’nin XMLHttpRequest’ten farkı nedir?
- Fetch API, XMLHttpRequest’e göre daha modern ve güçlü bir alternatiftir. Temel farklar şunlardır:
- Promise Tabanlı: Fetch, Promise’ler döndürerek
.then()ve.catch()zincirleriyle daha okunaklı ve yönetilebilir asenkron kod yazmayı sağlar. XHR ise genellikle geri çağırma (callback) fonksiyonlarına dayanır. - Basit Sözdizimi: Fetch’in sözdizimi daha basittir ve XHR’ın karmaşıklıklarından arındırılmıştır.
async/awaitDesteği:async/awaitile mükemmel bir uyum içinde çalışarak senkron koda benzeyen bir yazım deneyimi sunar.- Stream Desteği: Fetch, yanıt gövdesini bir Stream olarak ele alabilir, bu da büyük dosyaların işlenmesinde avantaj sağlar.
- Promise Tabanlı: Fetch, Promise’ler döndürerek
- Fetch ile nasıl hata yakalarım?
- Fetch’te iki tür hata vardır:
- Ağ Hataları: (örn. bağlantı kesilmesi, geçersiz URL) Bu hatalar doğrudan
.catch()bloğu tarafından yakalanır. - HTTP Hataları: (örn. 404 Not Found, 500 Internal Server Error) Fetch, bu durum kodlarını bir hata olarak kabul etmez. Yanıt nesnesinin
response.oközelliğifalsedöner. Bu tür durumları manuel olarak kontrol edip (if (!response.ok) throw new Error(...)) bir hata fırlatarak.catch()bloğunda yakalamanız gerekir.
- Ağ Hataları: (örn. bağlantı kesilmesi, geçersiz URL) Bu hatalar doğrudan
- CORS hatası nedir ve nasıl çözülür?
- CORS (Cross-Origin Resource Sharing) hatası, bir web tarayıcısının güvenlik politikası nedeniyle farklı bir kaynaktan (farklı bir domain, protokol veya port) gelen HTTP isteğini engellemesidir. Bu hata genellikle, isteği yaptığınız web sayfasının domain’i ile hedef API’nin domain’i farklı olduğunda ortaya çıkar. Çözümler şunları içerebilir:
- API Tarafında İzin: En yaygın çözüm, API sunucusunun
Access-Control-Allow-Originbaşlığını ayarlayarak sizin domain’inizden gelen isteklere izin vermesidir. - Proxy Kullanımı: Kendi sunucunuzda bir proxy oluşturarak, tarayıcının aynı kaynak kısıtlamasına takılmadan API isteğini yapabilirsiniz.
mode: 'no-cors'(Sınırlı Kullanım): Bu mod, tarayıcının CORS kontrolünü atlamasını sağlar ancak yanıt gövdesine erişiminizi kısıtlar ve genellikle önerilmez.
- API Tarafında İzin: En yaygın çözüm, API sunucusunun
- Fetch isteklerini iptal edebilir miyim?
- Evet,
AbortControllerarayüzünü kullanarak Fetch isteklerini iptal edebilirsiniz. BirAbortControllerörneği oluşturup, sinyalinifetch()fonksiyonuna iletirsiniz. Daha sonracontroller.abort()çağırarak isteği iptal edebilirsiniz. Bu, zaman aşımı (timeout) yönetimi veya kullanıcı navigasyonu gibi senaryolarda oldukça faydalıdır.