JavaScript’te AbortController: İptal Edilebilir Fetch ve Yarışan İstekleri Yönetmek
Fetch isteklerini iptal et, gereksiz trafiği kes ve yarışan API çağrılarını kontrol altına al.
Bir arama kutusuna yazarken her tuş vuruşunda API çağrısı yapmak kolaydır; zor olan ise eski istekleri iptal edip yalnızca en güncel sonucu ekrana yansıtmaktır. Bu yazıda AbortController ile iptal edilebilir fetch akışını, “son istek kazanır” (latest-only) yaklaşımını ve timeout desenini kısa örneklerle ele alacağız.
Neden iptal?
- Kullanıcı hızlı yazarken gereksiz ağ trafiğini azaltmak
- Yavaş dönen eski isteğin yeni veriyi ezmesini engellemek
- Sayfadan ayrılırken (route değişimi vb.) bekleyen istekleri temizlemek
1) Temel kullanım: fetch’i iptal etmek
AbortController bir signal üretir; fetch bu sinyali dinler. abort() çağrıldığında fetch AbortError ile reddedilir.
const controller = new AbortController();
fetch("/api/products", { signal: controller.signal })
.then(r => r.json())
.then(console.log)
.catch(err => {
if (err.name === "AbortError") return; // sessiz geç
console.error(err);
});
// Bir noktada iptal:
controller.abort();
2) “Son istek kazanır” deseni (typeahead/search)
Her yeni aramada bir önceki isteği iptal ederek sadece güncel sonucu işlersiniz.
let activeController = null;
async function search(query) {
// Önceki isteği iptal et
activeController?.abort();
const controller = new AbortController();
activeController = controller;
try {
const res = await fetch(`/api/search?q=${encodeURIComponent(query)}`, {
signal: controller.signal
});
if (!res.ok) throw new Error("HTTP " + res.status);
const data = await res.json();
// Bu controller hâlâ aktif mi? (ek güvenlik)
if (activeController !== controller) return;
renderResults(data);
} catch (err) {
if (err.name === "AbortError") return;
showError(err.message);
}
}
function renderResults(items) {
const ul = document.querySelector("#results");
ul.innerHTML = items.map(i => `<li>${i.name}</li>`).join("");
}
Bu yaklaşım özellikle:
- Arama/filtreleme
- Sonsuz kaydırma (scroll) içinde hızlı parametre değişimleri
- Sekmeler (tab) arasında hızlı geçiş
gibi senaryolarda net fayda sağlar.
3) Timeout: “Şu sürede dönmezse iptal et”
fetch’in yerleşik timeout’u yok. AbortController ile ekleyebilirsiniz.
async function fetchWithTimeout(url, { timeoutMs = 5000, ...options } = {}) {
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), timeoutMs);
try {
const res = await fetch(url, { ...options, signal: controller.signal });
return res;
} finally {
clearTimeout(id);
}
}
// Kullanım
fetchWithTimeout("/api/slow", { timeoutMs: 2000 })
.then(r => r.json())
.then(console.log)
.catch(err => {
if (err.name === "AbortError") console.warn("İstek zaman aşımına uğradı.");
else console.error(err);
});
4) Birden çok isteği tek sinyalle iptal etmek
Aynı signal birden fazla fetch’e verilebilir. Sayfadan ayrılırken toplu iptal için kullanışlıdır.
const controller = new AbortController();
const p1 = fetch("/api/user", { signal: controller.signal });
const p2 = fetch("/api/permissions", { signal: controller.signal });
// Route değişimi / component unmount benzeri durumda:
controller.abort();
Küçük notlar
AbortErrorbir hata türü ama çoğu UI akışında “beklenen” bir durumdur; log’u kirletmemek için filtreleyin.- İptal etmek her zaman sunucuda işlemi durdurmaz; ancak istemci tarafında yanıtı artık kullanmayacağınızı garanti eder.
Sonuç
AbortController, modern arayüzlerde “yarışan istekler” problemini basit ve temiz biçimde çözer: eski isteği iptal et, günceli göster. Özellikle arama ve filtreleme gibi kullanıcı etkileşimi yoğun ekranlarda hem performans hem de doğruluk açısından ciddi fark yaratır.