Başarısız olan bir async isteği exponential backoff ile yeniden deneyen bir retry fonksiyonu yazın.
Cevap
Fikir: istek başarısız olursa her denemede bekleme süresini ikiye katlayarak (base * 2^attempt) tekrar denemek, rastgele jitter ekleyerek çok sayıda istemcinin aynı anda sunucuya yüklenmesini önlemek.
const sleep = (ms, signal) =>
new Promise((resolve, reject) => {
const id = setTimeout(resolve, ms);
signal?.addEventListener("abort", () => {
clearTimeout(id);
reject(signal.reason);
}, { once: true });
});
async function retry(fn, {
retries = 3,
baseDelay = 300,
maxDelay = 5000,
shouldRetry = () => true,
signal,
} = {}) {
for (let attempt = 0; ; attempt++) {
try {
return await fn(attempt);
} catch (err) {
if (attempt >= retries || !shouldRetry(err) || signal?.aborted) throw err;
const exp = Math.min(maxDelay, baseDelay * 2 ** attempt);
const delay = Math.random() * exp; // "full jitter"
await sleep(delay, signal);
}
}
}
// Kullanım: sadece ağ hataları ve 5xx/429 için tekrar dene
const data = await retry(async () => {
const res = await fetch("/api/orders");
if (!res.ok) throw Object.assign(new Error("HTTP " + res.status), { status: res.status });
return res.json();
}, { shouldRetry: (e) => !e.status || e.status >= 500 || e.status === 429 });Tartışılacak noktalar
- Neyi tekrar denemeli? 4xx (400, 401, 404) hataları tekrar denemekle düzelmez. 429'da
Retry-Afterbaşlığına uyun. - Idempotency: POST gibi yan etkili istekleri tekrar etmek çift sipariş yaratabilir; idempotency key gerekir.
- Kullanıcı sayfadan ayrılırsa
AbortSignalile beklemeyi iptal edin. - TanStack Query gibi kütüphaneler bunu
retryveretryDelayseçenekleriyle hazır sunar.
İlgili JavaScript soruları
Bu konuda başka bir soru biliyor musun?
Mülakatta karşılaştığın soruları ekle, onaylandıktan sonra yayına alınsın.