Takip et

Fetch API’ye Giriş: Modern Web İstekleri İçin Temel Rehber

Fetch API’ye Giriş: Modern Web İstekleri İçin Temel Rehber Web uygulamaları geliştirirken, sunucu ile veri alışverişi yapmak kaçı

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 (Response nesnesi) 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 nedenle response.ok kontrolü ö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 şekilde response.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. Özellikle Content-Type, sunucuya gönderilen verinin formatını bildirir. Authorization baş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 nesnesini JSON.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/await Desteği: async/await ile 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.
Fetch ile nasıl hata yakalarım?
Fetch’te iki tür hata vardır:

  1. Ağ Hataları: (örn. bağlantı kesilmesi, geçersiz URL) Bu hatalar doğrudan .catch() bloğu tarafından yakalanır.
  2. 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ği false dö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.
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-Origin baş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.
Fetch isteklerini iptal edebilir miyim?
Evet, AbortController arayüzünü kullanarak Fetch isteklerini iptal edebilirsiniz. Bir AbortController örneği oluşturup, sinyalini fetch() fonksiyonuna iletirsiniz. Daha sonra controller.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.

Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.