JavaScript fetch ile API'den veri çekme: zaman aşımı, hata yönetimi, tekrar deneme

Çoğu örnek fetch(url).then(r => r.json()) diye geçer ama gerçek hayatta sunucu yavaş kalır, 500 döner ya da internet kopar. İşte projelerde gönül rahatlığıyla kullanabileceğin bir yardımcı fonksiyon:

/**
 * JSON getirir. Zaman aşımı, HTTP hata kontrolü ve tekrar deneme içerir.
 * @param {string} url
 * @param {{timeoutMs?: number, retries?: number, options?: RequestInit}} ayar
 */
async function guvenliFetch(url, { timeoutMs = 8000, retries = 2, options = {} } = {}) {
  for (let deneme = 0; deneme <= retries; deneme++) {
    const controller = new AbortController();
    const zamanlayici = setTimeout(() => controller.abort(), timeoutMs);
    try {
      const res = await fetch(url, { ...options, signal: controller.signal });
      if (!res.ok) {
        // 4xx hatalarında tekrar denemenin anlamı yok
        if (res.status < 500) throw new Error(`İstek hatası: ${res.status}`);
        throw new Error(`Sunucu hatası: ${res.status}`);
      }
      return await res.json();
    } catch (err) {
      const sonDeneme = deneme === retries;
      const istemciHatasi = err.message.startsWith("İstek hatası");
      if (sonDeneme || istemciHatasi) throw err;
      // 0.5 sn, 1 sn, 2 sn ... bekleyerek tekrar dene (exponential backoff)
      await new Promise(r => setTimeout(r, 500 * 2 ** deneme));
    } finally {
      clearTimeout(zamanlayici);
    }
  }
}

// Kullanım
try {
  const veri = await guvenliFetch("https://jsonplaceholder.typicode.com/todos/1");
  console.log(veri.title);
} catch (e) {
  console.error("Veri alınamadı:", e.message);
}

Öne çıkanlar

  • AbortController ile istek 8 saniyeyi geçerse iptal edilir; sayfa sonsuza kadar beklemez.
  • res.ok kontrolü şart: fetch 404 veya 500’de hata fırlatmaz, bunu çoğu kişi bilmez.
  • 5xx ve ağ hatalarında artan bekleme süresiyle tekrar dener; 4xx’te denemez.

Node.js 18 ve üzerinde fetch yerleşik olarak geliyor, ek paket kurmana gerek yok.