---
title: 'İptal ve Zaman Aşımı'
source: 'https://academia.sh/tr/kurslar/eszamansiz-javascript/iptal-ve-zaman-asimi'
course: 'Eşzamansız JavaScript ve Çalışma Zamanı'
language: tr
updated: '2026-08-17T18:09:44+00:00'
license: 'CC BY-SA 4.0'
---

# İptal ve Zaman Aşımı

İptal işareti kavramı, isteğin gerçekten durdurulması, zaman aşımının işaret üzerine kurulması, yarış tabanlı zaman aşımının neden yetersiz kaldığı ve işaretlerin birleştirilmesi.

Önceki ders iki boşlukla kapandı: hiç yanıt vermeyen bir kaynak sonsuza kadar beklenir ve
başlatılmış bir istekten vazgeçmenin yolu yoktur. İki boşluk da aynı eksikten doğar —
eşzamansız bir işlemi *dışarıdan* etkileyecek bir kanal yoktur.

Bu ders o kanalı kurar. Kanalın adı **iptal işareti (abort signal)**; zaman aşımı da
bunun üzerine kurulan özel bir durumdur. Ölçüm akışı burada durdurulabilir hale gelir.

## İptal İşareti

İptal düzeneği iki nesneden oluşur. **Denetleyici (controller)** iptali başlatan taraftadır
ve bir `abort` yöntemi taşır. **İşaret (signal)**, işi yapan tarafa verilir; iptal edilip
edilmediğini bildirir ve iptal anında bir olay yayar.

Ayrım önemlidir: işareti alan taraf iptal *edemez*, yalnız iptali *gözler*. Böylece iptal
yetkisi çağıranda kalır.

```js
import { createServer } from "node:http";

const sunucu = createServer((istek, yanit) => {
  const kimlik = setTimeout(() => {
    yanit.writeHead(200, { "content-type": "application/json" });
    yanit.end(JSON.stringify({ istasyon: "A1", deger: 21.4 }));
  }, 200);
  yanit.on("close", () => clearTimeout(kimlik));
});

await new Promise((karar) => sunucu.listen(0, "127.0.0.1", karar));
const taban = `http://127.0.0.1:${sunucu.address().port}`;

const denetleyici = new AbortController();
setTimeout(() => denetleyici.abort(), 20);

try {
  await fetch(`${taban}/olcum/A1`, { signal: denetleyici.signal });
  console.log("bu satır çalışmaz");
} catch (hata) {
  console.log("istek durduruldu:", hata.name);
}

try {
  await fetch(`${taban}/olcum/A1`, { signal: AbortSignal.timeout(20) });
} catch (hata) {
  console.log("zaman aşımı:", hata.name);
}

sunucu.close();
```

```
istek durduruldu: AbortError
zaman aşımı: TimeoutError
```

Sunucu iki yüz milisaniye sonra yanıt verecek biçimde kuruldu; iki istek de yirminci
milisaniyede sonlandı. Hata adları iki durumu ayırt eder: elle iptal `AbortError`, süre
sınırı `TimeoutError` üretir. Ayrım, kurtarma kararında kullanılır — kullanıcı vazgeçtiyse
yeniden denemek anlamsızdır, süre dolduysa anlamlı olabilir.

`AbortSignal.timeout` bir kısayoldur: belirtilen süre sonunda kendiliğinden iptal olan bir
işaret üretir. Zamanlayıcıyı elle kurmaya ve iptal etmeye gerek bırakmaz.

Sunucu tarafındaki `close` dinleyicisi de aynı düşüncenin karşılığıdır: istemci bağlantıyı
kestiğinde sunucu da bekleyen işini iptal eder. İptal, tek yönlü bir çağrı değil, iki uçta
da uygulanması gereken bir sözleşmedir.

## Kendi İşlevinize İptal Eklemek

İptal, ana ortamın ayrıcalığı değildir. Söz döndüren her işlev, seçenek nesnesinde bir
işaret kabul ederek aynı sözleşmeye katılabilir. Kurallar üçtür: işaret zaten iptal
edilmişse hemen reddet, iptal olayında kaynakları serbest bırak ve reddet, dinleyiciyi
bir kez çalışacak biçimde kaydet.

```js
const KAYNAK = {
  A1: { gecikme: 30, deger: 21.4 },
  B2: { gecikme: 10, deger: 19.8 },
};

function olcumGetir(istasyon, secenekler = {}) {
  const isaret = secenekler.signal;
  return new Promise((karar, red) => {
    if (isaret?.aborted) {
      red(isaret.reason);
      return;
    }
    const kayit = KAYNAK[istasyon];
    const kimlik = setTimeout(() => {
      console.log("kaynak: iş tamamlandı —", istasyon);
      karar({ istasyon, deger: kayit.deger });
    }, kayit.gecikme);

    isaret?.addEventListener(
      "abort",
      () => {
        clearTimeout(kimlik);
        console.log("kaynak: iş durduruldu —", istasyon);
        red(isaret.reason);
      },
      { once: true },
    );
  });
}

const denetleyici = new AbortController();
setTimeout(() => denetleyici.abort(new Error("toplama iptal edildi")), 15);

try {
  await olcumGetir("A1", { signal: denetleyici.signal });
} catch (hata) {
  console.log("çağıran gördü:", hata.message);
}

await new Promise((karar) => setTimeout(karar, 40));
console.log("bekleme bitti; A1 için başka çıktı olmadı");
```

```
kaynak: iş durduruldu — A1
çağıran gördü: toplama iptal edildi
bekleme bitti; A1 için başka çıktı olmadı
```

Son satır, iptalin gerçekten iş durdurduğunun kanıtıdır: kırk milisaniye daha beklendiği
halde "iş tamamlandı" iletisi hiç yazılmadı, çünkü zamanlayıcı temizlendi.

`abort` yöntemine verilen değer, işaretin `reason` alanına yerleşir ve reddetme nedeni
olur. Verilmezse ana ortam `AbortError` adlı bir hata üretir. Kendi hatanızı vermek,
iptal nedenini çağrı yığıtı olmadan taşımanın en doğrudan yoludur.

## Yarış Tabanlı Zaman Aşımı Neden Yetersiz

Zaman aşımı, birleştiriciler bilindiğinde ilk akla gelen biçimde de yazılabilir: işi bir
zamanlayıcıyla yarıştırmak. Bu çözüm beklemeyi keser, ama işi kesmez.

```js
const KAYNAK = {
  A1: { gecikme: 30, deger: 21.4 },
};

function olcumGetir(istasyon) {
  return new Promise((karar) => {
    const kayit = KAYNAK[istasyon];
    setTimeout(() => {
      console.log("kaynak: iş yine de tamamlandı —", istasyon);
      karar({ istasyon, deger: kayit.deger });
    }, kayit.gecikme);
  });
}

function zamanAsimi(sure) {
  return new Promise((karar, red) => {
    setTimeout(() => red(new Error(`zaman aşımı: ${sure} ms`)), sure);
  });
}

try {
  await Promise.race([olcumGetir("A1"), zamanAsimi(10)]);
} catch (hata) {
  console.log("çağıran gördü:", hata.message);
}

await new Promise((karar) => setTimeout(karar, 40));
console.log("bekleme bitti");
```

```
çağıran gördü: zaman aşımı: 10 ms
kaynak: iş yine de tamamlandı — A1
bekleme bitti
```

Çağıran onuncu milisaniyede hata aldı; iş otuzuncu milisaniyede tamamlandı. Yani sunucuya
gönderilen istek sürdü, yanıt geldi, bellek ve bağlantı tutuldu — yalnız sonucu kimse
kullanmadı.

Sonuçları üç başlıkta toplanır: kaynak boşa harcanır, sonuçlanmamış söz ve kapattığı
değerler bellekte kalır, ve yan etkili bir işlemde — örneğin bir kaydın yazılmasında —
"zaman aşımına uğradı" denen işlem aslında tamamlanmış olabilir.

Kural şudur: **yarış beklemeyi sonlandırır, iptal işi sonlandırır.** İkisi birbirinin
yerine geçmez; doğru zaman aşımı, süre dolduğunda iptali tetikleyendir.

## İşaretleri Birleştirmek

Bir işlemin birden çok iptal nedeni olabilir: kullanıcı vazgeçti, süre doldu, üst düzey
işlem iptal edildi. `AbortSignal.any`, birden çok işareti tek işarette toplar; hangisi
önce iptal olursa birleşik işaret onun nedeniyle iptal olur.

```js
const kullanici = new AbortController();
const birlesik = AbortSignal.any([kullanici.signal, AbortSignal.timeout(30)]);

birlesik.addEventListener("abort", () => {
  console.log("birleşik işaret durduruldu; neden:", birlesik.reason.name);
});

setTimeout(() => kullanici.abort(), 10);

await new Promise((karar) => setTimeout(karar, 50));
console.log("kullanıcı işareti durduruldu mu:", kullanici.signal.aborted);
```

```
birleşik işaret durduruldu; neden: AbortError
kullanıcı işareti durduruldu mu: true
```

Kullanıcı iptali onuncu milisaniyede geldiği için birleşik işaret onunla sonuçlandı; otuz
milisaniyelik süre sınırı hiç devreye girmedi. Bu kalıp, iptali çağrı ağacı boyunca
taşımayı mümkün kılar: üst düzey bir işlemin işareti, alt işlemlerin kendi süre
sınırlarıyla birleştirilerek aşağı aktarılır.

## İptalin Sınırları

İki sınır açıkça bilinmelidir.

İptal **işbirliğine dayanır.** İşareti gözlemeyen bir işlev iptal edilemez; iptal isteği
yalnız işareti dinleyenlere ulaşır. Bu yüzden söz döndüren her işlev, uzun sürebilecek
işlerde işaret parametresini kabul etmelidir.

İptal **geri alma değildir.** Sunucuya ulaşmış bir isteğin sunucudaki etkisi iptalle
geri alınmaz; yalnız yanıtın beklenmesinden vazgeçilir. Yan etkili işlemlerde bu ayrım,
sonraki dersteki yeniden deneme kararının temelini oluşturur.

## Özet

- İptal, denetleyici ve işaret olmak üzere iki nesneyle kurulur; işareti alan taraf iptali
  yalnız gözler.
- Söz döndüren kendi işlevleriniz, işareti kabul edip iptal olayında kaynaklarını serbest
  bırakarak aynı sözleşmeye katılabilir.
- `AbortSignal.timeout` süre sınırını işaret olarak üretir; elle iptal `AbortError`, süre
  sınırı `TimeoutError` verir.
- Yarış tabanlı zaman aşımı yalnız beklemeyi keser; iş sürer, kaynak tutulur, yan etki
  gerçekleşebilir.
- `AbortSignal.any` birden çok iptal nedenini tek işarette toplar ve iptalin çağrı ağacı
  boyunca aktarılmasını sağlar.

## Sonraki Adım

İptal ve zaman aşımı, başarısızlığı belirlenmiş hale getirdi: artık bir isteğin ne zaman
biteceği biliniyor. Geriye başarısızlıktan sonra ne yapılacağı kalıyor. Sonraki ders geçici
hataları kalıcı olanlardan ayırır, hangi işlemlerin güvenle yeniden denenebileceğini
belirler, bekleme sürelerinin neden artırılarak seçildiğini ve deneme bütçesinin neden
sınırlı tutulduğunu gösterir. Ölçüm akışı böylece hem durdurulabilir hem de dayanıklı hale
gelecek.
