Menu
Playground'da Dene

JavaScript Callback Fonksiyonları ve Callback Hell

JavaScript'te callback fonksiyonları nasıl çalışır? Fonksiyonu argüman olarak geçmekten error-first pattern'e, callback hell'den promise'lere kadar her şey.

Callback, Başka Bir Fonksiyona Verdiğin Fonksiyondur

JavaScript'te fonksiyonlar da birer değerdir. Onları değişkenlere atayabilir, dizilere koyabilir ve — burada en önemlisi — argüman olarak başka fonksiyonlara geçirebilirsin. Bir fonksiyonu başka bir fonksiyona, sonradan çağırabilsin diye verdiğinde, geçirdiğin o fonksiyona callback denir.

index.js
Output
Click Run to see the output here.

greet fonksiyonu, formatter'ın ne yaptığını ne biliyor ne de umursuyor. Sadece bir isimle çağırıp sonucu kullanıyor. Davranışı, farklı callback'ler geçirerek sen belirliyorsun. Zaten callback'lerin var olma sebebi de tam olarak bu esneklik.

Senkron Callback'ler Hemen Çalışır

Her callback asenkron değildir. Hâlihazırda kullandığın array metodlarının çoğu callback tabanlıdır ve bunlar callback'i senkron olarak çalıştırır — yani dış çağrı geri dönmeden önce:

index.js
Output
Click Run to see the output here.

map, filter ve reduce; hepsi bir callback alır ve her eleman için bu callback'i anında, orada çağırır. map geri döndüğünde, callback'e yapılan tüm çağrılar çoktan tamamlanmıştır. Sonraya bırakılan hiçbir şey yoktur.

Bu, klasik bir higher-order function kalıbıdır — "al sana iş, al sana yapma şekli, sonucu bana ver." Event loop'un bu işe karışmadığını unutma.

Asenkron callback'ler sonra çalışır

İnsanlar "callback" dediğinde aslında çoğunlukla asenkron olanları kastediyor. Vakit alan bir API'ye — bir zamanlayıcı, bir network isteği, bir dosya okuma — bir fonksiyon veriyorsun; API de iş bittiğinde senin fonksiyonunu geri çağırıyor.

index.js
Output
Click Run to see the output here.

Çıktı sırası şöyle: "önce", "sonra", ve bir saniye sonra "timer çalıştı". setTimeout programınızı duraklatmaz. Callback'i runtime'a teslim eder, hemen geri döner ve script'in geri kalanı çalışmaya devam eder. Bir saniye sonra event loop callback'i alıp çalıştırır.

Bu "hemen dön, sonra geri çağır" mantığı, addEventListener'dan eski Node.js dosya API'lerine kadar JavaScript'teki tüm asenkron callback API'lerinin temel zihin modelidir.

Error-First Callback Kuralı (Node.js)

Promise'ler ortaya çıkmadan önce Node.js belirli bir callback yapısını standart haline getirdi: ilk argüman hata (ya da null), geri kalanı da asıl sonuç olur. Eski kodlarda ve bazı kütüphanelerde hâlâ bu kalıpla karşılaşırsınız.

index.js
Output
Click Run to see the output here.

Çağıran taraf önce err'e bakar ve dolu geliyorsa hemen çıkar. Ancak o zaman sonuca güvenir. Bu bir gelenek — dil seviyesinde zorunlu değil — ama (err, result) => ... imzasını bir kez gördükten sonra her yerde tanırsınız.

Callback Hell Nedir?

İşler, bir asenkron adımın başka bir adımın sonucuna bağlı olmasıyla çığırından çıkıyor. Her callback bir öncekinin içine yerleştirilmek zorunda kalıyor ve kod sağa doğru merdiven gibi uzayıp gidiyor:

index.js
Output
Click Run to see the output here.

Bu, meşhur "piramit canavarı" ya da bilinen adıyla callback hell. Birkaç sebepten dolayı insanın canını sıkar:

  • Kod akışı yukarıdan aşağıya değil, zikzak çizerek ilerler.
  • Her katmanda aynı if (err) return ... kalıbı tekrar eder.
  • İçteki bir callback exception fırlattığında bu dıştakilere yayılmaz — hataları her katmanda ayrı ayrı yakalamak zorundasın.
  • Küçük bir refactor, tüm bloğu baştan girintilemek demek.

Named function'lara ayırarak biraz düzleştirebilirsin, ama asıl sorun — yani ham callback'lerle asenkron kompozisyonun hantal olması — yerinde duruyor. Promise'ler tam da bunu çözmek için tasarlandı.

Dikkat Edilmesi Gereken İki Tuzak

Callback'i yanlışlıkla çağırma. Bir callback geçerken fonksiyonun kendisini geçersin — onu çağırıp dönen sonucu değil.

index.js
Output
Click Run to see the output here.

this konusunda dikkatli ol. Callback olarak verdiğin normal bir fonksiyon içinde this kullanıyorsan, this'in değeri fonksiyonun tanımlandığı yere değil, çağrıldığı yere göre belirlenir. Arrow function'lar ise this'i bulundukları scope'tan miras aldığı için bu sorunu en baştan ortadan kaldırır:

index.js
Output
Click Run to see the output here.

Arrow function'lar, tam da bu yüzden satır içi callback'lerde varsayılan tercih hâline geldi.

Callback vs Promise

Callback'ler hâlâ senkron API'lerde (map, forEach, sort), olay dinleyicilerinde (element.addEventListener("click", ...)) ve düşük seviyeli runtime hook'larında karşımıza çıkıyor. Ama tek bir sonuç üreten asenkron işler söz konusu olduğunda ekosistem neredeyse tamamen promise'lere geçti.

Kısa bir karşılaştırma:

  • Callback'ler — doğrudan ve sade ama iyi birleşmiyorlar. Hata yönetimini her adımda elle yapmak gerekiyor.
  • Promise'ler — gelecekteki bir sonucu temsil eden bir değer. .then() ile zincirliyorsun, hataları tek bir .catch() ile yakalıyorsun ve o piramit düzleşiyor.

Yine de callback'leri iyi anlamak şart: promise'lerin temelinde onlar var ve olay temelli kodun her yerinde karşına çıkıyorlar. Ama artık yeni asenkron API'leri ham callback'lerle yazdığın çok nadir görülüyor.

Sırada: Promise'ler

Promise'ler, "şu hazır olduğunda bunu yap" fikrini alıp; etrafta dolaştırabileceğin, zincirleyebileceğin ve birleştirebileceğin bir nesneye sarıyor. Bir sonraki sayfanın konusu bu — ve aynı zamanda modern JavaScript'in asenkron işleri çoğunlukla nasıl ele aldığına, yani async/await'e açılan köprü.

Sıkça Sorulan Sorular

JavaScript'te callback fonksiyonu nedir?

Callback, başka bir fonksiyona argüman olarak geçirdiğin ve o fonksiyonun uygun bir anda çağırdığı bir fonksiyondur. Örneğin setTimeout(() => console.log('hi'), 1000) ifadesinde arrow function bir callback olarak geçiliyor — setTimeout bu fonksiyonu saklıyor ve zaman dolduğunda çağırıyor. JavaScript'in 'şu hazır olunca bunu yap' ihtiyacını karşılamak için kullandığı ilk yöntem callback'lerdir.

Senkron ve asenkron callback arasındaki fark nedir?

Senkron callback, onu alan fonksiyon çalışırken hemen yürütülür — [1, 2, 3].map(x => x * 2) çağrısında map geri dönmeden önce callback üç kez çalışır. Asenkron callback ise saklanır ve bir olay gerçekleştikten sonra çağrılır — setTimeout, fs.readFile ve DOM event listener'ları hep bu şekilde çalışır. Asenkron callback'ler kodunun geri kalanını bloklamaz.

Callback hell nedir ve nasıl kurtulunur?

Callback hell, birbirine bağımlı asenkron callback'lerin üst üste iç içe yazılmasıyla ortaya çıkan piramit görünümüdür. Hem akışı takip etmek hem de hata yönetimi yapmak bir kabusa dönüşür. Çözüm: .then() zincirleriyle promise kullanmak ya da daha iyisi async/await'e geçmek — ikisi de o piramidi düzleştirip okunabilir bir hale getirir.

Coddy ile kodlamayı öğren

BAŞLA