---
title: 'Geri Çağrılar'
source: 'https://academia.sh/tr/kurslar/eszamansiz-javascript/geri-cagrilar'
course: 'Eşzamansız JavaScript ve Çalışma Zamanı'
language: tr
updated: '2026-08-17T18:09:43+00:00'
license: 'CC BY-SA 4.0'
---

# Geri Çağrılar

Hata öncelikli geri çağrı sözleşmesi, sıralı ve birlikte işlemenin elle kurulması, iç içe geçme sorunu ve denetimin çağrılan tarafa devredilmesinin doğurduğu belirsizlikler.

Zamanlayıcılar geri çağrıyı zamana bağladı. Gerçek bir kaynakta bağlanılan şey zaman
değil sonuçtur: ölçüm hazır olduğunda haber ver, olmazsa nedenini bildir. Bu, eşzamansız
programlamanın ilk yaygın arayüzüdür ve sözleri anlamak için önce onun sınırlarını görmek
gerekir.

Bu ders ölçüm kaynağını geri çağrı tabanlı bir arayüze dönüştürür, üç istasyonu önce
sırayla sonra birlikte okur ve bu yaklaşımın nerede yetersiz kaldığını gösterir.

## Hata Öncelikli Sözleşme

Eşzamansız bir işlev sonucunu `return` ile veremez; çünkü sonuç, işlev döndüğünde henüz
yoktur. Bunun yerine sonucu bir **geri çağrı (callback)** aracılığıyla verir.

Hata da aynı yoldan gelmelidir: önceki derste görüldüğü gibi, geri çağrının içinden
atılan bir hata çağıranın `try` bloğuna ulaşmaz. Yerleşik çözüm, geri çağrının ilk
parametresini hataya ayırmaktır — **hata öncelikli geri çağrı (error-first callback)**
sözleşmesi.

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

function olcumGetir(istasyon, gericagri) {
  const kayit = KAYNAK[istasyon];
  if (kayit === undefined) {
    setTimeout(() => gericagri(new Error(`bilinmeyen istasyon: ${istasyon}`)), 0);
    return;
  }
  setTimeout(() => gericagri(null, { istasyon, deger: kayit.deger }), kayit.gecikme);
}

olcumGetir("A1", (hata, olcum) => {
  if (hata) {
    console.log("A1 hatası:", hata.message);
    return;
  }
  console.log("A1 ölçümü:", olcum.deger);
});

olcumGetir("Z9", (hata, olcum) => {
  if (hata) {
    console.log("Z9 hatası:", hata.message);
    return;
  }
  console.log("Z9 ölçümü:", olcum.deger);
});

console.log("istekler kaydedildi");
```

```
istekler kaydedildi
Z9 hatası: bilinmeyen istasyon: Z9
A1 ölçümü: 21.4
```

Üç ayrıntı sözleşmenin parçasıdır. Birincisi, hata yolunda bile geri çağrı eşzamansız
çağrılır; bilinmeyen istasyon hatası bile `setTimeout` ile bir sonraki tura bırakıldı.
İkincisi, hata varken ikinci parametre anlamsızdır. Üçüncüsü, hata denetimi her çağrı
noktasında elle yazılır — bu, dersin sonunda tekrar edilecek bir maliyettir.

## Sıralı İşleme ve İç İçe Geçme

Üç istasyonu sırayla okuyup ortalamayı hesaplamak isteyin. Her adımın sonucu bir sonraki
adımın geri çağrısında kullanılabildiği için, adımlar iç içe girer.

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

function olcumGetir(istasyon, gericagri) {
  const kayit = KAYNAK[istasyon];
  if (kayit === undefined) {
    setTimeout(() => gericagri(new Error(`bilinmeyen istasyon: ${istasyon}`)), 0);
    return;
  }
  setTimeout(() => gericagri(null, { istasyon, deger: kayit.deger }), kayit.gecikme);
}

olcumGetir("A1", (hataA, a) => {
  if (hataA) {
    console.log("hata:", hataA.message);
    return;
  }
  olcumGetir("B2", (hataB, b) => {
    if (hataB) {
      console.log("hata:", hataB.message);
      return;
    }
    olcumGetir("C3", (hataC, c) => {
      if (hataC) {
        console.log("hata:", hataC.message);
        return;
      }
      const ortalama = (a.deger + b.deger + c.deger) / 3;
      console.log("sıra:", [a.istasyon, b.istasyon, c.istasyon].join(" -> "));
      console.log("ortalama:", ortalama.toFixed(2));
    });
  });
});
```

```
sıra: A1 -> B2 -> C3
ortalama: 21.43
```

Program doğrudur, ama üç gözlem yapılabilir. Girinti, mantıksal karmaşıklıkla değil adım
sayısıyla artar; on adım on kat girinti demektir. Hata denetimi üç kez, birbirinin aynısı
biçimde tekrarlanır. Son olarak, akışın sonucunu kullanacak kod en içeride kalır; adım
eklemek en dıştan en içe kadar dokunmayı gerektirir.

Bu düzenin yaygın adı geri çağrı piramididir. Asıl sorun görüntü değil, **birleştirilebilir
olmamasıdır**: iki eşzamansız adımı birleştiren genel bir işleç yoktur; her birleşim elle
yazılır.

## Birlikte İşleme: Eşgüdümün Bedeli

Üç istasyon birbirinden bağımsızsa sırayla beklemek gereksizdir; üçü birlikte
başlatılabilir. Bu durumda sonuçların toplanması, sayaç ve bayrak tutan bir eşgüdüm
işlevi gerektirir.

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

function olcumGetir(istasyon, gericagri) {
  const kayit = KAYNAK[istasyon];
  if (kayit === undefined) {
    setTimeout(() => gericagri(new Error(`bilinmeyen istasyon: ${istasyon}`)), 0);
    return;
  }
  setTimeout(() => gericagri(null, { istasyon, deger: kayit.deger }), kayit.gecikme);
}

function tumunuGetir(istasyonlar, gericagri) {
  const sonuclar = new Array(istasyonlar.length);
  let kalan = istasyonlar.length;
  let bitti = false;

  istasyonlar.forEach((istasyon, dizin) => {
    olcumGetir(istasyon, (hata, olcum) => {
      if (bitti) return;
      if (hata) {
        bitti = true;
        gericagri(hata);
        return;
      }
      console.log("geldi:", istasyon);
      sonuclar[dizin] = olcum;
      kalan -= 1;
      if (kalan === 0) {
        bitti = true;
        gericagri(null, sonuclar);
      }
    });
  });
}

tumunuGetir(["A1", "B2", "C3"], (hata, olcumler) => {
  if (hata) {
    console.log("hata:", hata.message);
    return;
  }
  console.log("sonuç sırası:", olcumler.map((o) => o.istasyon).join(" "));
});
```

```
geldi: B2
geldi: C3
geldi: A1
sonuç sırası: A1 B2 C3
```

Geliş sırası gecikmelere göre B2, C3, A1 oldu; buna karşın sonuç dizisi istek sırasını
korudu. Bunu sağlayan şey, sonuçların dizine göre yerleştirilmesidir — sıraya güvenmek
yerine konum kullanmak, eşzamansız toplamada temel kalıptır.

`bitti` bayrağı da gereklidir: hata sonrası gelen sonuçların geri çağrıyı ikinci kez
tetiklemesini engeller. Yani doğru bir "hepsini bekle" işlevi, sayaç ve bayrak olmak
üzere iki ayrı durum tutar. Bu iş, sözlerle birlikte kütüphaneye taşınacak ve tek satıra
inecek.

## Denetimin Çağrılana Devri

Geri çağrı verdiğinizde, işlevinizin ne zaman ve kaç kez çalışacağına siz karar vermezsiniz;
çağırdığınız kod karar verir. Buna **denetimin devri (inversion of control)** denir ve üç
somut belirsizlik doğurur.

**Geri çağrı hiç çağrılmayabilir.** Kaynak yanıt vermezse hiçbir şey olmaz; program ne
sonuç ne hata görür, sessizce bekler. Zaman aşımı, bu boşluğu kapatmak için ayrıca kurulur.

**Geri çağrı birden çok kez çağrılabilir.** Sözleşme bunu yasaklar ama dil zorlamaz.

```js
function hataliOlcumGetir(istasyon, gericagri) {
  setTimeout(() => {
    gericagri(null, { istasyon, deger: 21.4 });
    gericagri(null, { istasyon, deger: 21.4 });
  }, 5);
}

let adet = 0;
let toplam = 0;

hataliOlcumGetir("A1", (hata, olcum) => {
  adet += 1;
  toplam += olcum.deger;
  console.log("adet:", adet, "toplam:", toplam.toFixed(1));
});
```

```
adet: 1 toplam: 21.4
adet: 2 toplam: 42.8
```

Tek bir ölçüm iki kez toplandı. Hata, toplayan tarafta değil kaynaktadır; ama sonucuna
toplayan taraf katlanır.

**Geri çağrı bazen eşzamanlı çağrılabilir.** Önbellek isabetinde beklemeye gerek olmadığı
düşünülerek geri çağrının doğrudan çağrılması, akışın sırasını değiştirir.

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

function olcumGetir(istasyon, gericagri) {
  const kayit = KAYNAK[istasyon];
  setTimeout(() => gericagri(null, { istasyon, deger: kayit.deger }), kayit.gecikme);
}

const onbellek = new Map();

function onbellekliGetir(istasyon, gericagri) {
  if (onbellek.has(istasyon)) {
    gericagri(null, onbellek.get(istasyon));
    return;
  }
  olcumGetir(istasyon, (hata, olcum) => {
    onbellek.set(istasyon, olcum);
    gericagri(hata, olcum);
  });
}

let durum = "hazırlanıyor";

onbellekliGetir("B2", (hata, olcum) => {
  console.log("1 — ilk çağrı, durum:", durum);
  durum = "işleniyor";
  onbellekliGetir("B2", () => {
    console.log("2 — önbellekten gelen çağrı, durum:", durum);
  });
  durum = "iç çağrıdan sonra";
  console.log("3 — iç çağrıdan sonraki satır, durum:", durum);
});

durum = "hazır";
```

```
1 — ilk çağrı, durum: hazır
2 — önbellekten gelen çağrı, durum: işleniyor
3 — iç çağrıdan sonraki satır, durum: iç çağrıdan sonra
```

İkinci çağrının geri çağrısı, kendisinden sonraki satırdan **önce** çalıştı; çünkü
önbellek isabetinde eşzamanlı çağrıldı. Aynı arayüz, aynı çağrı, iki farklı sıra. Kural
nettir: bir arayüz geri çağrıyı bazen eşzamanlı bazen eşzamansız çağırmamalıdır. Önbellek
isabetinde de sonuç bir sonraki tura bırakılmalıdır.

## Geri Çağrının Bıraktığı Boşluk

Bu dersteki programlar çalışır ve hiçbirinde dil hatası yoktur. Buna karşın hepsi aynı
eksikleri paylaşır: hata yolu her düzeyde elle yazılır, `try`/`catch` işe yaramaz,
adımların birleştirilmesi için genel bir işleç yoktur, ve sözleşme ihlalleri (hiç çağırmama,
iki kez çağırma, eşzamanlı çağırma) dil tarafından engellenmez.

Sonuç, eşzamansız bir işlemin **birinci sınıf bir değer** olmamasıdır. Geri çağrı,
sonucu alan tarafı bildirir; ama işlemin kendisini temsil eden, saklanabilen,
döndürülebilen, başkasına verilebilen bir nesne yoktur.

## Özet

- Eşzamansız bir işlev sonucunu döndüremez; hata öncelikli geri çağrı sözleşmesi hem
  sonucu hem hatayı tek bir yoldan iletir.
- Sıralı adımlar geri çağrılarla iç içe girer; girinti ve hata denetimi adım sayısıyla
  büyür.
- Birlikte çalışan istekleri toplamak sayaç ve bayrak gerektirir; sonuçlar geliş sırasına
  değil konuma göre yerleştirilir.
- Denetimin devri üç belirsizlik doğurur: geri çağrının hiç çağrılmaması, birden çok kez
  çağrılması ve bazen eşzamanlı çağrılması.
- Geri çağrı düzeninde eşzamansız işlem birinci sınıf bir değer değildir; bu nedenle
  birleştirilemez.

## Sonraki Adım

Bu boşluğun yanıtı, "sonucu henüz belli olmayan bir işlem"i bir değer olarak temsil
etmektir. Sonraki ders bu değeri tanımlar: söz. Sözün üç durumu, durumların yalnız bir kez
değişebilmesi, geri çağrıların mikro göreve alınması ve zincirlemenin her adımda yeni bir
söz üretmesi — bu dersteki dört eksiğin dördü de bu kurallardan çıkacak.
