TypeScriptÖrnek · ücretsiz40 satır
İstediğin kod
Ağ hatasında ve 5xx yanıtta üstel geri çekilmeyle yeniden deneyen, zaman aşımlı bir fetch sarmalayıcısı.
TypeScript
export interface YenidenDenemeSecenekleri { denemeSayisi?: number; ilkBekleme?: number; zamanAsimiMs?: number;} /** Ağ hatasında ve 5xx yanıtta üstel geri çekilmeyle yeniden dener. */export async function fetchRetry( url: string, init: RequestInit = {}, { denemeSayisi = 3, ilkBekleme = 400, zamanAsimiMs = 10_000, }: YenidenDenemeSecenekleri = {},): Promise<Response> { let sonHata: unknown; for (let deneme = 0; deneme < denemeSayisi; deneme++) { const kontrol = new AbortController(); const sayac = setTimeout(() => kontrol.abort(), zamanAsimiMs); try { const cevap = await fetch(url, { ...init, signal: kontrol.signal }); // 4xx istemci hatasıdır: tekrar denemek aynı yanıtı verir. if (cevap.ok || cevap.status < 500) return cevap; sonHata = new Error("HTTP " + cevap.status); } catch (hata) { sonHata = hata; } finally { clearTimeout(sayac); } if (deneme < denemeSayisi - 1) { const bekleme = ilkBekleme * 2 ** deneme + Math.random() * 100; await new Promise((coz) => setTimeout(coz, bekleme)); } } throw sonHata instanceof Error ? sonHata : new Error("fetch başarısız");}Nasıl çalışır
- Her deneme kendi `AbortController`ını kurar; zaman aşımı dolunca istek iptal edilir ve hata koluna düşer.
- 4xx yanıtta döngü kırılmaz, doğrudan yanıt döner: istemci hatasını tekrar denemek aynı sonucu verir, cevheri ve zamanı boşa harcar.
- Bekleme süresi `400ms → 800ms → 1600ms` diye ikiye katlanır; üstüne 0–100ms rastgele pay eklenir (aynı anda düşen bin istemci sunucuya aynı saniyede geri dönmesin).
- Son deneme de başarısızsa yakalanan asıl hata yeniden fırlatılır; sarmalayıcı hatayı yutmaz.
Dikkat
- `clearTimeout` `finally` içinde: hata yolunda da temizlenir, yoksa sayaç sızar ve Node süreci kapanmaz.
- POST gibi idempotent olmayan istekleri körlemesine tekrarlama — sunucu tarafında bir idempotency anahtarın yoksa aynı sipariş iki kez düşebilir.
- `init.signal` ile dışarıdan bir iptal sinyali verirsen bu kod onu ezer; iki sinyali birleştirmen gerekir (`AbortSignal.any`).
Nasıl test edilir
- Sunucuyu iki kez 503, üçüncüde 200 döndürecek şekilde taklit et; `fetch`in üç kez çağrıldığını ve son yanıtın döndüğünü doğrula.
- 404 dönen bir uç için `fetch`in bir kez çağrıldığını doğrula (4xx yeniden denenmez).
- Sahte zamanlayıcıyla (`vi.useFakeTimers`) zaman aşımını tetikle ve `AbortError`ın yakalandığını gör.