
Önceki makalelerde JavaScript'in asenkron yapısını ve callback fonksiyonlarını öğrendik. Ancak callback'ler bir noktadan sonra kontrol edilemez hale gelebilir. Bu duruma geliştiriciler arasında "Callback Hell" (Callback Cehennemi) denir. Bu makalede bu problemi anlayacak ve neden daha iyi çözümlere ihtiyacımız olduğunu göreceğiz.
Callback Nedir? (Hızlı Tekrar)
Callback, başka bir fonksiyona parametre olarak geçirilen ve daha sonra çağrılacak olan fonksiyondur:
function islemYap(callback) {
// Bir şeyler yap...
callback(); // Sonra bu fonksiyonu çağır
}
islemYap(function() {
console.log("İşlem tamamlandı!");
});Problem: Sıralı Asenkron İşlemler
Diyelim ki bir renk değiştirme animasyonu yapmak istiyorsunuz. Her renk 1 saniye görünsün:
// İstenen: Kırmızı → Turuncu → Sarı → Yeşil → Maviİlk Deneme: Callback Olmadan
setTimeout(function() {
document.body.style.backgroundColor = 'red';
}, 1000);
setTimeout(function() {
document.body.style.backgroundColor = 'orange';
}, 1000);
setTimeout(function() {
document.body.style.backgroundColor = 'yellow';
}, 1000);Problem: Hepsi aynı anda (1 saniye sonra) çalışır! Sadece sarıyı görürüz.
İkinci Deneme: Süreleri Toplama
setTimeout(function() {
document.body.style.backgroundColor = 'red';
}, 1000);
setTimeout(function() {
document.body.style.backgroundColor = 'orange';
}, 2000); // 1 + 1
setTimeout(function() {
document.body.style.backgroundColor = 'yellow';
}, 3000); // 1 + 1 + 1Bu çalışır ama kırılgan bir çözüm:
- Süreleri elle hesaplıyoruz
- Bir süreyi değiştirmek istesek, hepsini güncellememiz gerekir
- Mantıksal olarak bağlantısız görünüyor
Üçüncü Deneme: İç İçe Callback'ler
setTimeout(function() {
document.body.style.backgroundColor = 'red';
setTimeout(function() {
document.body.style.backgroundColor = 'orange';
setTimeout(function() {
document.body.style.backgroundColor = 'yellow';
setTimeout(function() {
document.body.style.backgroundColor = 'green';
setTimeout(function() {
document.body.style.backgroundColor = 'blue';
}, 1000);
}, 1000);
}, 1000);
}, 1000);
}, 1000);Bu çalışır ama... 😱
Callback Hell'e Hoş Geldiniz
Yukarıdaki koda bakın. Gördüğünüz şey Callback Hell:
┐
┐ │
┐ │ │
┐ │ │ │
┐ │ │ │ │
┐ │ │ │ │ │
}); │ │ │ │ │ │
}); │ │ │ │ │ │
}); │ │ │ │ │ │
}); │ │ │ │ │ │
└───┴───┴───┴───┴───┘
"Piramit of Doom"Gerçek Hayat Örneği: Kullanıcı Kayıt Süreci
Bir kullanıcı kayıt işlemi düşünün:
- E-posta'nın kullanılıp kullanılmadığını kontrol et
- Şifreyi hashle
- Kullanıcıyı veritabanına kaydet
- Hoş geldin e-postası gönder
- Kullanıcıyı giriş yap
Her adım asenkron ve bir öncekine bağlı:
emailKontrol(email, function(emailMevcut) {
if (emailMevcut) {
hataGoster("Bu e-posta zaten kayıtlı");
} else {
sifreHashle(sifre, function(hashliSifre) {
kullaniciKaydet(email, hashliSifre, function(kullanici) {
hosgeldinEmailiGonder(email, function(emailSonuc) {
if (emailSonuc.basarili) {
kullaniciyiGirisYap(kullanici, function(oturum) {
anaSayfayaYonlendir();
}, function(hata) {
hataGoster("Giriş yapılamadı: " + hata);
});
} else {
hataGoster("E-posta gönderilemedi");
}
}, function(hata) {
hataGoster("E-posta gönderilemedi: " + hata);
});
}, function(hata) {
hataGoster("Kayıt başarısız: " + hata);
});
}, function(hata) {
hataGoster("Şifre işlenemedi: " + hata);
});
}
}, function(hata) {
hataGoster("E-posta kontrol edilemedi: " + hata);
});Bu kod:
- ❌ Okunması çok zor
- ❌ Hata yönetimi karmaşık
- ❌ Debug etmek kabus
- ❌ Bakımı imkansız
Neden Bu Kadar Kötü?
1. Okunabilirlik Sıfır
Kod sağa doğru kayarak "piramit" oluşturuyor. Hangi kapanış parantezi hangi açılışa ait anlamak imkansız.
2. Hata Yönetimi Dağınık
Her callback için ayrı hata callback'i gerekiyor:
islemYap(
function(sonuc) { /* başarılı */ },
function(hata) { /* başarısız */ }
);3. Değişiklik Yapmak Zor
Bir adım eklemek veya çıkarmak istediğinizde, tüm iç içe yapıyı değiştirmeniz gerekiyor.
4. Hata Ayıklama Kabusu
Hangi satırda hata var? Hangi callback çalışmadı? Stack trace okumak imkansız hale geliyor.
Callback Hell'den Kaçış Yolları
Yol 1: Fonksiyonları Ayırma
function emailKontrolEt() {
emailKontrol(email, sifreIsle, hataYakala);
}
function sifreIsle(emailMevcut) {
if (emailMevcut) {
hataGoster("E-posta zaten kayıtlı");
return;
}
sifreHashle(sifre, kullaniciOlustur, hataYakala);
}
function kullaniciOlustur(hashliSifre) {
kullaniciKaydet(email, hashliSifre, emailGonder, hataYakala);
}
// ... devam ederBu biraz daha iyi ama hala ideal değil.
Yol 2: Named Functions (İsimli Fonksiyonlar)
setTimeout(kirmiziYap, 1000);
function kirmiziYap() {
document.body.style.backgroundColor = 'red';
setTimeout(turuncuYap, 1000);
}
function turuncuYap() {
document.body.style.backgroundColor = 'orange';
setTimeout(sariYap, 1000);
}
function sariYap() {
document.body.style.backgroundColor = 'yellow';
// ... devam eder
}Daha okunabilir ama hala bağımlılıklar karışık.
Yol 3: Promises (Söz Nesneleri) ⭐
İşte gerçek çözüm! Bir sonraki makalenin konusu:
// Callback Hell yerine:
renkDegistir('red', 1000)
.then(() => renkDegistir('orange', 1000))
.then(() => renkDegistir('yellow', 1000))
.then(() => renkDegistir('green', 1000))
.then(() => renkDegistir('blue', 1000))
.catch(hata => console.log("Bir şeyler yanlış gitti!"));Düz, okunabilir ve tek hata yakalama noktası!
Özet
Bu makalede öğrendiklerimiz:
✅ Callback Hell, iç içe geçmiş callback'lerin oluşturduğu karmaşadır
✅ Sıralı asenkron işlemler callback'lerle çok zor yönetilir
✅ Kod okunabilirliği, bakımı ve hata yönetimi zorlaşır
✅ Fonksiyonları ayırmak geçici bir çözümdür
✅ Gerçek çözüm: Promises (bir sonraki makalemiz!)
Bir sonraki makalede JavaScript Promises konusunu derinlemesine inceleyeceğiz.


