- Modern Asenkron Programlama (Modern Asynchronous Programming)
- API Entegrasyonu ve JSON Yönetimi (API Integration & JSON Management)
- Asenkron Akışta Güvenilirlik (Reliability in Asynchronous Flow)
- Kavramsal Temel (Conceptual Foundation)
- JavaScript'in Asenkron Mimarisi (JavaScript Asynchronous Architecture)
Asenkron Programlama Terimler Sözlüğü
Asynchronous Programming Glossary
Bu bölümdeki terimleri ezberlemenize gerek yoktur; konular içinde geçen kavramları daha rahat takip etmeniz için listelenmiştir.
Asenkron bir işlemin gelecekte üreteceği değeri ya da hatayı temsil eden, tek kez sonuçlanan sözleşme yapısıdır.
Promise yaşam döngüsünü tamamlayan geri çağrılar; resolve başarı değerini, reject ise hata nedenini zincire iletir.
Promise tabanlı kodu senkronmuş gibi yazmayı sağlayan dil sözdizimi; await ifadeleri fonksiyonu duraklatır, try/catch ile hata yönetilir.
JavaScript motorunun çağrı yığınını ve kuyrukları izlemesini sağlayan mekanizma; asenkron görevlerin ne zaman çalışacağını koordine eder.
Promise çözüm geri çağrılarının işlendiği yüksek öncelikli kuyruk; macrotask’lardan önce tamamen boşaltılır.
Tarayıcıda ağ istekleri gerçekleştiren modern arayüz; yanıt gövdesini JSON’a çevirmek için ek bir Promise döndürür.
Fetch gibi uzun süren işlemleri güvenli biçimde iptal etmeye yarayan kontrol nesnesi; signal özelliğiyle istekleri dinamik olarak sonlandırır.
Tekrarlanan ağ çağrılarının yalnızca ilk sonucunu geçerli kılan benzersiz anahtar; ödeme gibi kritik işlemlerde veri tutarlılığını korur.
Sürekli hata üreten servisleri geçici olarak devreden çıkaran koruma deseni; sistemin geri kalanını güvende tutar.
Yeniden deneme sürelerini üstel olarak artırarak yükü azaltan strateji; geçici hatalarda servisin toparlanmasına zaman tanır.
Asenkron Programlama ve JSON ( Ana Konu Giriş )
Fonksiyon,
kodun nasıl çalıştığını değil,
hangi sorunu çözdüğünü
anlatan bir yapıdır.
Detayları arka planda bırakır,
niyeti ön plana çıkarır.
Bu bölümde,
kodu satır satır düşünmek yerine,
davranışlara ayırarak
daha sade ve yönetilebilir
programlar yazma yaklaşımını inceleyeceğiz.
Modern Asenkron Programlama: Promises ve async/await Zaman Ötesi Soyutlama
Asenkron programlama, JavaScript'in Event Loop ve Callback Kuyrukları gibi düşük seviyeli mekanizmalarını anlamayı gerektirse de, modern standartlar bu karmaşık işleyişi daha kolay ve okunabilir hale getiren üst seviye soyutlama araçları sunar.
Bu araçlar, zaman alan işlemlerin ana iş parçacığını engellemeden, sistem kaynaklarını en verimli şekilde kullanmamıza olanak tanır.
Felsefi Dönüşüm: Callback Kaosundan Düzenli AkışaPromises ve async/await gibi modern yapılar, geliştiricileri geleneksel callback'lerin yarattığı kontrol edilemez karmaşadan ( Callback Hell ) kurtarmıştır.
Buradaki temel felsefi amaç, asenkron işlemleri, uzun zincirleme yapılar yerine senkron koda benzer doğrusal bir akışla yönetmektir.
Bu dönüşüm, kodun öngörülebilirliğini artırırken, sürdürülebilir bir mühendislik disiplini inşa eder.
İleri Seviye Kontrol: Nesne Tabanlı GelecekPromises, asenkron bir görevin nihai sonucunu ( başarı veya hata) temsil eden güçlü bir obje modelini hayatımıza sokmuştur.
Bu nesne, henüz tamamlanmamış bir işlemin "sözünü" (promise) tutar. async/await ise bu nesne tabanlı akışı, dilin söz dizimi seviyesinde daha sezgisel ve hataya dayanıklı hale getirir.
Karmaşık asenkron mantıklar, sanki satır satır hemen gerçekleşiyormuş gibi yazılabilir hale gelmiş, bu da modern web uygulamalarının güvenilirliği için vazgeçilmez bir standart olmuştur.
Sonuç olarak, modern asenkron yapılar JavaScript'in tek iş parçacıklı doğasını, karmaşıklığı soyutlayarak yönetmemizi sağlar.
Bu yeni nesil araçları kullanmak, kodun sadece teknik doğruluğunu değil, aynı zamanda mimari zarafetini de temsil eder.
Promises (Sözler): Callback Cehenneminden Kurtuluş Asenkron Sonuçların Objeleştirilmesi ve Değer Sözleşmesi
Promises, ECMAScript 2015 ile hayatımıza giren ve JavaScript'in asenkron mimarisindeki en büyük devrimdir.
Bu yapının doğuşu, "Callback Cehennemi" olarak bilinen, iç içe geçmiş fonksiyonların kodu sağa doğru büyüttüğü ve hata ayıklamayı imkansızlaştırdığı yapısal bir çıkmaza karşı geliştirilmiştir.
Geleneksel callback yapısında, her asenkron işlem bir sonrakini tetiklerken mantıksal derinlik kontrolden çıkıyor, hata yönetimi ise her bir katmanda ayrı ayrı yapılması gereken bir yük haline geliyordu.
Promise, bu süreci doğrusal, izlenebilir ve tek bir merkezden kontrol edilebilir hale getirmiştir.
Yeni Felsefe: Değer Sözleşmesi (Value Contract)Bir Promise, asenkron bir işlemin anlık sonucunu değil, o işlemin gelecekteki nihai sonucunu temsil eden bir obje modelidir.
Geliştirici, karmaşık callback'lerle uğraşmak yerine, bu sözleşme objesinin sunduğu zincirlenebilir metotları (.then(), .catch(), .finally()) kullanarak asenkron akışı yönetir.
Bu durum, kodun hem okunabilirliğini artırır hem de asenkron işlemleri senkron bir mantık akışına yaklaştırarak zihinsel karmaşayı minimize eder.
Özet olarak, Promises yapısı, JavaScript'i asenkronluğun yarattığı "sağa doğru büyüme" kaosundan kurtarıp, "aşağıya doğru akan" temiz ve sürdürülebilir bir mimariye taşımıştır.
Bu birimler, modern web geliştirmede asenkron veri transferinin en temel güvenlik subabı ve organizasyon aracıdır.
Promise Durumları (State) Yaşam Döngüsü Kesinliği ve Değişmezlik Felsefesi
Bir Promise, oluşturulduğu andan itibaren sonuca ulaşana kadar yaşam döngüsünde üç temel durumdan birinde bulunur.
Bu durumlar, asenkron işlemin o anki "varlık sebebini" tanımlar ve JavaScript motoruna işlemin hangi evrede olduğu bilgisini kesin olarak iletir.
Promise mimarisi, bir kez sonuçlandıktan sonra durumun asla değişemeyeceği ilkesi üzerine kurulmuştur.
Yaşam Döngüsünün Üç HaliPromise nesnesinin zaman içindeki yolculuğu şu duraklardan geçer:
- Pending (Beklemede): Başlangıç durumudur. İşlem henüz tamamlanmamış, ne başarıya ulaşmış ne de hata almıştır. Promise'in "sözünü" tutmak için beklediği nötr evredir.
- Fulfilled (Çözüldü): Asenkron işlemin başarıyla sonuçlandığı andır. Bu durumda Promise, resolve() fonksiyonu aracılığıyla bir değer döndürür.
- Rejected (Reddedildi): İşlemin başarısızlıkla sonuçlandığı durumdur. reject() fonksiyonu tetiklenir ve bir hata mesajı/objesi üretilir.
Bir Promise, Fulfilled veya Rejected durumlarından herhangi birine ulaştığında Settled olarak kabul edilir.
Bu, işlemin nihai sonucuna ulaştığı ve artık "aktif" bir görev olmadığını belirtir.
Felsefi Önem: Promise settled olduktan sonra durumu dondurulur.
Eğer bir Promise bir kez başarıyla çözüldüyse, daha sonra kodun başka bir yerinde hata vermesi veya durumunun değişmesi imkansızdır.
Bu sarsılmaz güvenilirlik, asenkron akışların tahmin edilebilir olmasını sağlar.
Sonuç olarak, Promise Durumları, asenkronluğun kaotik doğasını disipline eden bir takvim gibidir.
Bu yapı sayesinde bir işlemin nerede tıkandığını, ne zaman çözüldüğünü ve mühürlendiğini kesin bir doğrulukla takip edebiliriz.
|
Durum
|
İngilizce Adı
|
Açıklama
|
Sonuç ve Devam
|
|---|---|---|---|
|
Pending
|
Pending
|
Başlangıç Durumu:
Asenkron işlem henüz tamamlanmamış, sonuç belirsizdir. |
Bu durumdayken Promise, çözülmeyi bekler.
|
|
Fulfilled
|
Fulfilled
|
Başarı Durumu:
İşlem başarıyla tamamlanmıştır ve Promise bir değerle çözülmüştür. |
Zincirdeki .then()
metodu tetiklenir.
|
|
Rejected
|
Rejected
|
Hata Durumu:
İşlem, bir hata nedeniyle başarısız olmuş veya reddedilmiştir. |
Zincirdeki .catch()
metodu tetiklenir.
|
Promise Oluşturma ve Çalışma Prensibi Executor Mekanizması ve Kontrol Akışı
Bir Promise'in temel gücü, asenkron bir görevin yürütülmesini düzenleyen ve nihai sonucunu belirleyen Kurucu ve Executor fonksiyonunda yatar.
Bir Promise her zaman new Promise(executor) yapısı kullanılarak inşa edilir.
Kritik Detay: Executor fonksiyonu, Promise objesi oluşturulduğu anda, hemen ve senkron olarak çalışır, görevi, zaman alacak olan
asenkron süreci derhal tetiklemektir.
Executor Fonksiyonunun Kontrol MekanizmasıJavaScript motoru, Executor fonksiyonuna iki adet özel callback fonksiyonu enjekte eder.
Bu iki fonksiyon, asenkron işlemin kaderini belirleyen anahtar mekanizmalardır:
- Resolve(value): Asenkron işlem başarıyla tamamlandığında çağrılır. Promise'i fulfilled (çözülmüş) durumuna geçirir. İletilen değer, zincirin devamındaki .then() bloğuna aktarılır.
- Reject(reason): İşlem sırasında bir aksaklık oluştuğunda tetiklenir. Promise'i rejected durumuna taşır. Hata detayı genellikle bir Error objesi olarak .catch() bloğuna fırlatılır.
Promise mimarisinin en sarsılmaz kuralı şudur: Bir Promise bir kez Settled durumuna geçtikten sonra, durumu asla geri döndürülemez veya değiştirilemez.
Eğer Executor fonksiyonu içinde yanlışlıkla birden fazla kez resolve veya reject çağrısı yapılırsa, JavaScript motoru sadece ilk çağrıyı dikkate alır; diğer tüm çağrılar sessizce göz ardı edilir.
Bu, asenkron bir işlemin tek ve tutarlı bir nihai sonuca sahip olma garantisidir.
Sonuç olarak, Promise oluşturma süreci, belirsiz bir zaman dilimini mühürlenmiş bir sözleşmeye dönüştürür.
Executor fonksiyonu sayesinde asenkron operasyonlar, başlangıçtan bitişe kadar disiplinli bir yönetim şablonuna tabi tutulur.
Zincirleme Metotlar .then(), .catch(), .finally()
Promises, Callback Cehennemi'nin yarattığı iç içe girintili kod karmaşasını çözmek için, asenkron işlemin sonuçlarını ele alan zincirlenebilir metotlar sunar.
Bu metotlar, asenkron akışı senkron koda benzer, yukarıdan aşağıya ve organize bir şekilde yazmayı mümkün kılar.
Mimari Devrim ve Boru Hattı MantığıZincirleme Yeteneği: geliştiricinin "Önce veriyi çek, sonra işle, sonra kaydet" gibi ardışık asenkron görevleri, her adımın sonucunun bir sonrakinin girdisi olacağı bir boru hattı (pipeline) mantığıyla kurgulamasını sağlar.
Bu dönüşüm, kodu nasıl yapacağını söyleyen imperatif bir yapıdan, bildirimsel bir yapıya taşır.
Her bir adımın kendi .then() bloğunda izole edilmesi, okunabilirliği ve hata ayıklama verimliliğini artırır.
Bu sayede, uzun ve karmaşık asenkron görevler bile yönetilebilir, küçük mantık parçalarına ayrılır.
Temel Zincirleme ve Hata Yönetimi Örneği .then() ve .catch()
// Promise Yaratma (Asenkron görevi simüle eder)
const asenkronIslem = new Promise((resolve, reject) => {
const basarili = true; // Görev sonucunu belirleyen koşul
setTimeout(() => {
if (basarili) {
resolve("Veri başarıyla alındı: Kaynak A"); // Başarı
} else {
reject("HATA: Ağ bağlantısı kesildi."); // Hata
}
}, 1000); // 1 saniye gecikme
});
// Promise Zincirinin Başlatılması
asenkronIslem
// Başarı Durumu (onFulfilled)
.then(sonuc => {
console.log(`1. Adım Başarılı: ${sonuc}`);
// Veriyi dönüştürüp yeni bir Promise/değer döndürerek zinciri devam ettirir.
return "2. Adım İşlendi.";
})
// İkinci .then() birincinin dönüş değerini alır.
.then(yeniSonuc => {
console.log(`2. Adım Başarılı: ${yeniSonuc}`);
})
// Hata Durumu (Zincirdeki herhangi bir reject'i yakalar)
.catch(hata => {
console.error(`Kritik Hata Yakalandı: ${hata}`);
});
console.log("Program akışı beklemiyor...");
// Çıktı: Program akışı beklemiyor... (Hemen çalışır, asenkronluk kanıtı)
// 1 saniye sonra: 1. Adım Başarılı: Veri başarıyla alındı: Kaynak A
// Hemen ardından: 2. Adım Başarılı: 2. Adım İşlendi.
Temizlik İşlemleri Örneği .finally()
function veriCekmeSimulasyonu(url) {
// Yükleme animasyonunu başlat
console.log(`[UI] Yükleme göstergesi açıldı...`);
// Basit bir Promise döndürür (hata ile çözülecek)
return new Promise((resolve, reject) => {
setTimeout(() => {
reject("Sunucu 500 Hatası"); // Promise reddediliyor
}, 500);
});
}
veriCekmeSimulasyonu("api/veri")
// Hata Yakalanır
.catch(hata => {
console.error(`HATA: ${hata} (Kullanıcıya gösterildi)`);
})
// En sonunda, sonuç ne olursa olsun (hata bile olsa) çalışır.
.finally(() => {
// Temizlik: Yükleme animasyonunu kapatma işlemi garanti edilir.
console.log(`[UI] Yükleme göstergesi KAPATILDI.`);
});
// Çıktı:
// [UI] Yükleme göstergesi açıldı...
// 500ms sonra:
// HATA: Sunucu 500 Hatası (Kullanıcıya gösterildi)
// [UI] Yükleme göstergesi KAPATILDI. (Temizlik başarıyla yapıldı)
Değer Dönüşümü ve Akış Kontrolü .then() Metodu ve Veri Pipelining Mekanizması
.then() metodu, Promise zincirinin temel yürütme birimidir ve bir asenkron işlem hattında verinin nasıl işleneceğini, dönüştürüleceğini ve bir sonraki aşamaya nasıl aktarılacağını tanımlar.
Bu metot, bir Promise nihai sonuca ulaştığında tetiklenecek olan mantıksal birimleri sisteme kaydeder.
Callback Yapısı ve Esnekliği.then() metodu, fonksiyonel olarak iki ayrı opsiyonel callback kabul eder:
- OnFulfilled (Başarı İşleyicisi): Promise çözüldüğünde devreye girer. Gelen veriyi manipüle etmek ve zincirin devamına "temizlenmiş" veriyi aktarmakla yükümlüdür.
- OnRejected (Hata İşleyicisi): Reddedilme durumunda hatayı yakalar. Ancak modern mimarilerde bu sorumluluk, daha temiz bir söz dizimi sunan .catch() metoduna devredilir.
Zincirlemeyi mümkün kılan sihirli özellik şudur: .then() metodu, her zaman ve kesinlikle yeni bir Promise döndürür.
Siz içeride sadece basit bir sayı döndürseniz bile, JavaScript bunu otomatik olarak çözülmüş bir Promise'e paketler.
Bu mekanizma, asenkron adımların birbirine eklenmesini ve verinin bir aşamadan diğerine transformasyon uğrayarak akmasını sağlar.
Sonuç olarak, .then() yapısı, asenkron akışı dikeyde ve okunaklı bir hiyerarşiye sokar.
Bu sayede geliştirici, karmaşık işlemleri küçük, test edilebilir ve birbirini takip eden mantıksal dilimlere bölme disiplini kazanır.
Paralel Promise Yönetimi ve Orkestrasyon Statik Metotlar ve Kolektif Asenkron Kontrol
Static Promise Metotları, JavaScript'e yalnızca ardışık zincirleme yeteneği kazandırmakla kalmaz; aynı zamanda birden fazla bağımsız asenkron görevi paralel olarak başlatma ve bu görevlerin sonuçlarını tek bir merkezden koordine etme gücü verir.
Bu yapı, karmaşık veri toplama süreçlerini ve sistem başlatma rutinlerini tek bir bildirimsel kod satırıyla yönetmemizi sağlar.
Orkestrasyon Felsefesi: Merkezi KontrolBu statik metotlar, geliştiriciye asenkron görevleri bir "orkestra şefi" edasıyla yönetme gücü verir.
Tek tek callback'lerle uğraşmak yerine, tüm görevleri bir dizi ( array ) halinde işleme alırız.
Örneğin: Bir uygulamanın ayağa kalkması için gereken tüm modüllerin aynı anda yüklenmesini zorunlu kılabilir veya en hızlı yanıt veren sunucuyu seçebiliriz.
Hata Yönetimi Stratejisi: Fail-Fast vs. Kapsamlı RaporlamaMetot seçimi, aslında uygulamanın hata toleransını belirler. Mimaride iki temel yaklaşım öne çıkar:
- Fail-Fast (Hızlı Başarısızlık): Promise.all() kullanıldığında, eğer görevlerden biri bile hata verirse, sistem diğerlerini beklemeden derhal reddedilir. Bu, kritik bağımlılıkların olduğu senaryolar için idealdir.
- Resilience (Dayanıklılık): Promise.allSettled() kullanıldığında, bazı görevler hata alsa bile tüm süreç tamamlanır ve her görevin durumu (başarı/hata) detaylı bir rapor olarak sunulur.
Tüm bunların sonucu olarak, Statik Promise Metotları, asenkron dünyada kaosu disipline eden en güçlü mühendislik araçlarıdır.
Bu metotlar sayesinde işlemlerin birbirini beklemesi yerine, kaynakları maksimum verimlilikle kullanarak toplam işlem süresini radikal bir şekilde düşürebiliriz.
|
Metot
|
Odak Noktası
(Rolü) |
Başarı Durumu (Fulfilled)
|
Hata / Reddedilme Durumu (Rejected)
|
|---|---|---|---|
|
Promise.all()
|
Toplu Başarı
(Hepsi Ya Da Hiçbiri) |
Girdi dizisindeki TÜM Promise'ler başarılı olduğunda çözülür.
|
Fail-Fast (Hemen Reddetme):
Promise'lerden HERHANGİ BİRİ reddedildiği anda, diğerlerini beklemeden o hatayla reddedilir. |
|
Promise.race()
|
Hız/Yarışma
(İlk Biten) |
Dizideki Promise'lerden İLK Settled (çözülmüş veya
reddedilmiş)
olanın
durumunu benimser.
İlk biten başarılıysa Promise çözülür. |
İlk biten Promise hata ile reddedilirse, bu Promise anında
reddedilir.
Geri kalan Promise'ler yok sayılır. |
|
Promise.allSettled()
|
Kapsamlı Raporlama
(Hepsini Bitir) |
Girdi dizisindeki TÜM Promise'ler Settled (çözülmüş veya
reddedilmiş)
duruma geçtiğinde çözülür.
|
Asla Reddedilmez:
Daima çözülür ve her bir Promise'in nihai durumunu ve sonucunu (status: 'fulfilled' / 'rejected') detaylandıran bir dizi obje döndürür. |
|
Promise.any()
|
Alternatif Kaynak
(İlk Başarılı) |
Dizideki Promise'lerden İLK başarıyla çözülen olanın
değerini döndürerek çözülür.
|
Hata:
Girdi dizisindeki TÜM Promise'ler reddedilirse reddedilir. Aksi halde bir tanesinin başarılı olması yeterlidir. |
Fail-Fast: Hepsi Ya Da Hiçbiri Promise.all()
// Gecikmeli bir Promise üreten yardımcı fonksiyon
const gorevUret = (isim, sure, basarili = true) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (basarili) {
console.log(`[BAŞARILI] ${isim} (${sure}ms) tamamlandı.`);
resolve(isim);
} else {
console.error(`[HATA] ${isim} başarısız oldu.`);
reject(isim + " Hata");
}
}, sure);
});
};
console.log("--- 1. PROMISE.ALL(): KRİTİK GÖREVLER (Fail Fast) ---");
const kritikGorevler = [
gorevUret("DB Bağlantısı", 300),
gorevUret("Kullanıcı Ayarları", 100),
gorevUret("Gerekli Lisans Kontrolü (HATA)", 500, false) // Hata ile sonuçlanacak
];
Promise.all(kritikGorevler)
.then(sonuclar => {
console.log("✅ ALL: Tüm kritik görevler tamamlandı:", sonuclar);
})
.catch(ilkHata => {
// En hızlı hata (Burada 'Kullanıcı Ayarları' değil, ilk reddedilen) yakalanır.
console.error("❌ ALL KIRILMASI: Zincir erken kesildi. Hata:", ilkHata);
});
// Sonuç: Görevler tamamlanmaz, hata ile hemen catch'e düşülür (Fail-Fast).
Hız/Yarışma: İlk Biten Kazanır Örneği Promise.race()
// Gecikmeli bir Promise üreten yardımcı fonksiyon
const gorevUret = (isim, sure, basarili = true) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (basarili) {
console.log(`[BAŞARILI] ${isim} (${sure}ms) tamamlandı.`);
resolve(isim);
} else {
console.error(`[HATA] ${isim} başarısız oldu.`);
reject(isim + " Hata");
}
}, sure);
});
};
console.log("\n--- 2. PROMISE.RACE(): İLK BİTENİ AL ---");
const yarisanGorevler = [
gorevUret("Sunucu A (50ms HATA)", 50, false), // En hızlı biten (Hata)
gorevUret("Sunucu B (200ms BAŞARI)", 200),
gorevUret("Sunucu C (500ms BAŞARI)", 500)
];
Promise.race(yarisanGorevler)
.then(kazanan => {
console.log("🏆 RACE: Başarılı kazanan:", kazanan);
})
.catch(ilkRed => {
// İlk biten 50ms'lik hata olduğu için yakalanır.
console.error("❌ RACE: İlk biten işlem hataydı:", ilkRed);
});
// Sonuç: Hata döndürülür, çünkü ilk Settled olan (50ms) hata ile sonuçlandı.
Kapsamlı Rapor: Hepsini Bitir Örneği Promise.allSettled()
// Gecikmeli bir Promise üreten yardımcı fonksiyon
const gorevUret = (isim, sure, basarili = true) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (basarili) {
console.log(`[BAŞARILI] ${isim} (${sure}ms) tamamlandı.`);
resolve(isim);
} else {
console.error(`[HATA] ${isim} başarısız oldu.`);
reject(isim + " Hata");
}
}, sure);
});
};
console.log("\n--- 3. PROMISE.ALLSETTLED(): TÜM SONUÇLARI RAPORLA ---");
const raporGorevler = [
gorevUret("Rapor A", 200), // Başarılı
gorevUret("Rapor B", 500, false), // Hata
gorevUret("Rapor C", 100), // Başarılı
];
// Asla catch'e düşmez.
Promise.allSettled(raporGorevler)
.then(sonuclar => {
console.log("✅ ALL SETTLED: Tüm rapor durumları alındı (Hatalılar dahil):");
// Sonuçlar, her bir görevin durumu ve çıktısını içerir.
sonuclar.forEach((item, index) => {
console.log(` - [Gorev ${index + 1}] Durum: ${item.status} | Sonuç: ${item.status === 'fulfilled' ? item.value : item.reason}`);
});
});
Alternatif Kaynak: İlk Başarılıyı Seç Örneği Promise.any()
// Gecikmeli bir Promise üreten yardımcı fonksiyon
const gorevUret = (isim, sure, basarili = true) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (basarili) {
console.log(`[BAŞARILI] ${isim} (${sure}ms) tamamlandı.`);
resolve(isim);
} else {
console.error(`[HATA] ${isim} başarısız oldu.`);
reject(isim + " Hata");
}
}, sure);
});
};
console.log("\n--- 4. PROMISE.ANY(): İLK BAŞARILI ALTERNATİFİ BUL ---");
const alternatifGorevler = [
gorevUret("Yedek Sunucu", 800, false), // Hata
gorevUret("Ana Kaynak", 100), // Başarı (En hızlı başarılı olan)
gorevUret("Çok Yavaş Kaynak", 50, false) // Hata (En hızlı bitse bile, hata olduğu için beklenir)
];
Promise.any(alternatifGorevler)
.then(ilkBasariliSonuc => {
// Hatalı Promise'leri görmezden gelir, ilk başarılı olanı yakalar.
console.log("✅ ANY: İlk başarılı sonuç alındı:", ilkBasariliSonuc);
})
.catch(topluHata => {
// Tüm kaynaklar başarısız olursa buraya düşer.
console.error("❌ ANY: Tüm kaynaklar başarısız oldu.");
});
// Sonuç: 'Ana Kaynak' 100ms'de çözülür ve diğer hataları ve yavaş Promise'i durdurur.
Senkron Görünümlü Asenkron Kod (ES2017) async/await: Söz Dizimi Şekeri ve Mimari Ergonomi
async/await yapısı, ECMAScript 2017 ile JavaScript ekosistemine dahil olan ve Promise tabanlı asenkron yapıyı tamamen dönüştüren bir dönüm noktasıdır.
Bu modern yapı, karmaşık asenkron işlemleri yönetmenin en kolay, en okunabilir ve mantıksal hatalara karşı en dirençli yoludur.
Geliştiriciyi, asenkronluğun getirdiği yapısal gürültüden kurtararak doğrudan iş mantığına odaklanmasını sağlar.
Felsefesi: Söz Dizimi Şekeri (Syntactic Sugar)Teknik olarak async/await, arka planda çalışan yeni bir motor yaratmaz; aksine mevcut Promise mimarisinin üzerine inşa edilmiş bir
"Söz Dizimi Şekeri"dir ( Syntactic Sugar).
Temel felsefesi, .then() zincirlerinin neden olduğu görsel karmaşıklığı ve "sağa doğru büyüme" eğilimini ortadan kaldırmaktır.
Kod okunduğunda, asenkron adımlar sanki geleneksel senkron kod gibi yukarıdan aşağıya doğru akar.
Kod Ergonomisi ve Hata KontrolüBu yalınlaştırma, geliştirici ergonomisi açısından devrim niteliğindedir.
Asenkron akış, try...catch blokları ile sarmalanarak senkron kodda olduğu gibi kontrol edilebilir.
Hata yönetimi artık asenkron zincirin her halkasında ayrı ayrı değil, tek bir merkezi noktadan senkron hata yakalama mantığıyla yönetilir.
Bu durum, kodun hem bakımını kolaylaştırır hem de mantıksal izlenebilirliğini zirveye taşır.
Sonuç olarak, async/await yapısı, JavaScript'in asenkron yeteneklerini en yüksek soyutlama seviyesine taşımıştır.
Geliştiricilere, karmaşık zaman yönetimlerini temiz ve okunabilir bir dille ifade etme gücü vererek modern yazılımın mimari standartlarını belirlemiştir.
Promise Garantisi ve Otomatik Sarmalama async Anahtar Kelimesinin Sözleşme Gücü
async anahtar kelimesi, bir fonksiyonu tanımladığınızda JavaScript motoru ile kurduğunuz en yüksek seviyeli asenkron sözleşmedir.
Bir fonksiyonun başına bu ifadeyi eklediğinizde, motora şu kesin beyanı yapmış olursunuz:
"Bu fonksiyonun gövdesi ne döndürürse döndürsün, dış dünyaya yansıyan sonuç daima bir Promise olacaktır."
Mekanizma: Otomatik Promise Sarmalamaasync fonksiyonun içindeki return deyimi, geleneksel fonksiyonlardan farklı bir mikro-mimari ile çalışır, siz fonksiyon içinde yalın bir değer döndürseniz dahi, arka planda "Promise Motoru" devreye girer:
- Değer Sarmalama: Eğer fonksiyon return "Onaylandı" gibi ilkel bir değer döndürürse, motor bunu otomatik olarak Promise.resolve("Onaylandı") haline getirir.
- Hata Sarmalama: Eğer fonksiyon içinde bir hata (throw) fırlatılırsa, bu durum motor tarafından anında yakalanır ve Promise.reject(error) olarak paketlenir.
Bu otomatik sarmalama mekanizması, asenkron kodun mimari tutarlılığını sağlar.
Fonksiyonu çağıran dış kod, dönen yanıtın bir Number mı yoksa bir Promise mi olduğunu kontrol etme yükünden kurtulur.
Sonucun her zaman "Thenable" olacağı garantisi, karmaşık zincirlerin kırılmadan çalışmasını mümkün kılar.
Sonuç olarak, async kelimesi sadece bir işaretçi değil, bir mühendislik güvencesidir.
Bu garanti sayesinde asenkron veri akışları, belirsizlikten arınarak tahmin edilebilir ve güvenli bir hiyerarşiye kavuşur.
Asenkron Duraklama ve Senkron Akış await Anahtar Kelimesi ve Yürütme Askıya Alma Mekanizması
await anahtar kelimesi, asenkron programlamanın söz dizimini kökten basitleştiren ve asenkron süreçleri senkron bir akış hiyerarşisine oturtan en kritik mimari araçtır.
Temel işlevi, bir Promise çözülene kadar fonksiyonun ilerleyişini duraklatmak ve çözüm anında gelen veriyi "sanki hemen oradaymış gibi" bir dönüş değeri olarak yakalamaktır.
Asenkron Duraklama Mekanizması (Non-Blocking)En kritik teknik detay, bu duraklamanın niteliğidir: Non-Blocking duraklama.
JavaScript motoru bir await ifadesiyle karşılaştığında, ilgili async fonksiyonun yürütülmesini askıya alır, ancak bu, ana iş parçacığının donduğu anlamına gelmez.
Event Loop İlişkisi: Fonksiyon durakladığında, bu fonksiyonun geri kalan kodu Microtask Queue'ya emanet edilir.
Event Loop, bu bekleme süresinde boş durmaz; Call Stack'teki diğer görevleri ( kullanıcı tıklamaları, animasyonlar,
diğer senkron kodlar) işlemeye devam eder.
Promise çözüldüğü anda, askıya alınan fonksiyon Call Stack'e geri çağrılır ve kaldığı yerden devam eder ve bu sayede kullanıcı arayüzü asla kilitlenmez.
Hata Yönetimi: Try...Catch Entegrasyonuawait yapısının sağladığı en büyük ergonomik avantaj, hata yönetimini senkron kod disiplinine yaklaştırmasıdır.
Promise zincirlerindeki .catch() metodu yerine, artık geleneksel try...catch blokları kullanılır.
Reddedilmiş bir Promise ile karşılaşan await, o hatayı senkron bir exception gibi fırlatır.
Bu istisna, fonksiyonu çevreleyen en yakın catch bloğu tarafından yakalanır.
Bu mekanizma, asenkron hataların takibini son derece sezgisel ve "okunabilir" kılar.
Özet ile, await operatörü, asenkronluğun karmaşık zaman tünelini düz bir çizgiye indirger.
Bu sayede geliştirici, zaman alan işlemlerle uğraşırken mantıksal odağını kaybetmez ve temiz, sürdürülebilir kod mimarileri inşa edebilir.
Senkron Akışın Simülasyonu Örneği async/await
function simulePromise(basarili) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (basarili) {
resolve(100);
} else {
reject("İşlem Başarısız");
}
}, 500);
});
}
async function veriIsle() {
try {
console.log("1. Veri çekme başlatıldı.");
// await ile bekliyoruz; fonksiyon duruyor ama tarayıcı donmuyor.
const ilkDeger = await simulePromise(true);
console.log(`2. İlk değer alındı: ${ilkDeger}`);
const ikinciDeger = await simulePromise(false); // Hata fırlatacak
console.log("Bu satır asla çalışmaz.");
} catch (hata) {
// Hata yakalandığında buraya atlanır (rejected Promise).
console.error(`3. Hata Yakalandı: ${hata}`);
return "İşlem sonlandı.";
}
}
veriIsle();
console.log("<<< Ana Program Akışı Devam Ediyor >>>");
API Entegrasyonu ve JSON Yönetimi: fetch API Modern Ağ İletişimi
Modern web uygulamaları, sadece istemci tarafında ( tarayıcıda ) statik kodlar çalıştırmakla kalmaz; yaşayan, dinamik bir içerik sağlamak için neredeyse tamamen uzak sunucularla veri alışverişine dayanır.
Tarayıcıların yerleşik API'lerinden olan fetch API, JavaScript'te bu ağ isteklerini ( network requests ) yapmanın en modern, Promise tabanlı ve esnek yöntemidir.
Tarihsel Geçiş: XHR'den Modern Standartlarafetch, eski ve karmaşık olan, callback yapısına aşırı bağımlı XMLHttpRequest yapısının yerini almak üzere tasarlanmıştır.
Bu geçiş, Promise mimarisinin dilin çekirdeğine entegre edilmesinin getirdiği en önemli mimari ilerlemelerden biridir.
fetch ile birlikte ağ istekleri, karmaşık olay dinleyicileri yerine temiz, zincirlenebilir ve okunabilir bir arayüze kavuşmuştur.
Asenkron Sözleşme ve Non-Blocking FelsefesiTemel felsefesi, tüm ağ operasyonlarını doğal olarak asenkron bir süreç olarak ele almaktır.
Bir fetch fonksiyonu çağrıldığında, ağdan yanıt gelene kadar ana iş parçacığını asla kilitlemez (non-blocking).
Geriye daima bir Promise döndürerek, geliştiricinin ağ bekleme süresini async/await veya Promise zincirleri ile güvenle yönetmesine olanak tanır.
Sonuç olarak, fetch API, asenkron yetenekleri web'in evrensel veri formatı olan JSON ile birleştirerek tarayıcıyı güçlü bir veri terminaline dönüştürür.
Bu mimariyi kavramak, sunucu-istemci arasındaki iletişim köprüsünü kurmanın ilk ve en önemli adımıdır.
API Mimarisi ve Asenkron Sözleşme fetch() Fonksiyonunun Yapısal ve Felsefi Temelleri
fetch() fonksiyonu, JavaScript dünyasında ağ isteği yapmanın getirdiği karmaşık ve gürültülü detayları ( header konfigürasyonları, bağlantı el sıkışmaları, stream yönetimi ) arka planda çözen devasa bir soyutlama katmanıdır.
Geliştiriciye sunduğu sade arayüz, aslında fetch'in sadece bir fonksiyon çağrısı değil, tarayıcı ile kurulan bir asenkron sözleşme olduğu felsefesine dayanır.
Sözleşme Garantisi (Promise Consistency)Fetch mimarisinin en güçlü yanı sunduğu Sözleşme Garantisidir.
Fonksiyon tetiklendiği anda, ağ durumu ne olursa olsun geriye daima bir Promise objesi döndürür.
Bu yapısal tutarlılık, fetch'i geleneksel ve yönetimi zor callback yapılarından kurtararak, modern async/await ve Promise zincirleri ile tam uyumlu, öngörülebilir bir araç haline getirir.
Mimari Rol: Non-Blocking Veri TransferiPromise tabanlı bu mimari, ağ üzerinden gelen verinin ne kadar sürede ulaşacağından bağımsız olarak Call Stack'i bloke etmeden (non-blocking) çalışır.
Ağ isteği Web API katmanına devredilirken, JavaScript motoru diğer görevlerine devam eder.
Yanıt ulaştığında ise Event Loop mekanizması bu asenkron sözleşmeyi tamamlayarak veriyi işleme hattına geri kazandırır.
Sonuç olarak, fetch API, asenkron programlamanın pratik dünyadaki en somut uygulamasıdır.
Geliştiriciye sunduğu bu asenkron sözleşme sayesinde, karmaşık veri akışları üzerinde tam kontrol sağlanırken, uygulamanın akıcılığı ve performansı korunmuş olur.
Promise Tabanlı İşleyiş ve İlk Çözülme Fetch API'nin İki Aşamalı Çözülme (Resolution) Mimarisi
Fetch API'nin işleyişini kavramak, onu geleneksel asenkron metodlardan ayıran iki aşamalı çözülme stratejisini anlamayı gerektirir.
Çoğu geliştiricinin aksine, Fetch'in ilk aşaması verinin tamamını değil, sadece bağlantının kurulup kurulmadığını mühürleyen bir teknik sözleşme sunar.
fetch(url) çağrısı yapıldığında dönen ilk Promise, verinin tamamı geldiğinde değil; sunucudan HTTP başlıkları alındığı anda çözülür.
Bu aşamada tarayıcı, sunucuya ulaşmış, el sıkışmış ve "Yanıt veriyorum" mesajını almıştır.
Ancak verinin ( body ) kendisi henüz stream ( akış ) halindedir ve tam olarak belleğe yüklenmemiştir.
Kritik Nüans: Başarı ve Hata AyrımıBu ilk Promise'in çözülmesi, gelen HTTP durum kodundan tamamen bağımsızdır. Teknik bir paradoks olarak; sunucu 404 (Not Found) veya
500 (Server Error) gibi bir hata kodu döndürse bile, ağ bağlantısı fiziksel olarak kurulduğu için bu Promise fulfilled durumuna geçer.
Geliştirici, mantıksal hatayı bu aşamada response.ok özelliği üzerinden kontrol etmek zorundadır.
Tek Ret (Rejection) Durumu: Fetch tarafından dönen ilk Promise, sadece ve sadece fiziksel bir ağ hatası ( internet kesintisi,
DNS problemleri, sunucunun kapalı olması ) oluştuğunda rejected durumuna geçer, bu, Fetch'in hata yönetimindeki en kritik mimari disiplindir.
Özetlemek gerekirse, Fetch API'de ilk çözüm aşaması, veriyi değil bağlantı güvenliğini temsil eder.
Bu ayrımı doğru yönetmek, hem ağ hatalarını hem de sunucu tabanlı mantıksal hataları birbirinden izole ederek daha sağlam bir API entegrasyonu kurmanın anahtarıdır.
İki Aşamalı Asenkron Veri İşlem Hattı Bağlantı Kurulumu ve Veri Ayrıştırma Ayrımı
Fetch API kullanımındaki en kritik teknik derinlik, verinin sunucudan talep edilmesi ve uygulama tarafında işlenmesinin tek bir atomik adımda değil, her biri kendi Promise'ini döndüren iki bağımsız asenkron aşamada gerçekleşmesidir.
Bu tasarım, Fetch'in asenkron işlem hattı felsefesinin bir yansımasıdır: Ağ seviyesindeki bağlantıyı, uygulama seviyesindeki veri formatından ayırmak.
1. Aşama: Bağlantı ve Başlık Çözümlemesiİlk aşamada, fetch() çağrısı yapıldığında tarayıcı sunucuya bir el sıkışma isteği gönderir.
Bu aşamanın Promise'i, sunucudan ilk HTTP yanıt başlıkları ( headers ) geldiği anda çözülür.
Ancak dikkat edilmelidir ki; bu noktada henüz gövde verisi tam olarak indirilmemiştir; sadece hattın açık ve sunucunun yanıt vermeye hazır olduğu mühürlenmiştir.
2. Aşama: Veri Akışının (Stream) Objeleşmesiİkinci aşama, gelen ham veri akışının JavaScript tarafından okunup anlamlı bir formata ( genellikle JSON ) dönüştürülmesini kapsar.
.json() metodu çağrıldığında, arka planda yeni bir asenkron süreç başlar.
Bu süreç, sunucudan gelen tüm veri paketlerinin tamamlanmasını bekler ve ardından bu ham metni bir JavaScript Nesnesine ayrıştırır.
Mimari Avantaj: Bu ikili yapı sayesinde, geliştirici "bağlantı hatası" ( internet yok ) ile "veri format hatası" ( gelen JSON bozuk ) durumlarını birbirinden izole edebilir.
Bu ayrım, modern web uygulamalarında hata ayıklama sürecini ve kullanıcıya verilecek geri bildirimin kalitesini doğrudan artırır.
Sonuç olarak, İki Aşamalı Asenkron Veri Hattı, JavaScript'in zamanı ne kadar hassas yönettiğinin bir kanıtıdır.
Geliştirici, bu iki Promise'i ardışık yöneterek, veriyi ham bir sinyalden stratejik bir bilgiye dönüştürme disiplini kazanır.
|
Metot
|
Rolü ve Teknik İşlevi
|
Hata Yönetimi ve Kontrol
|
|---|---|---|
|
fetch(url)
|
Sunucuya fiziksel erişim sağlar ve HTTP başlıklarını (headers)
içeren ilk Promise'i döndürür.
|
Sadece Ağ Hatası: Bağlantı kopukluğu veya DNS
sorunlarında reddedilir. HTTP
404/500 kodlarında hata fırlatmaz.
|
|
response.json()
|
Yanıtın gövdesini (body) okur; ham string metni JavaScript nesnesine
ayrıştırır.
|
JSON Ayrıştırma Hatası: Gelen metin geçerli JSON
formatında değilse (bozuk veri)
Promise reddedilir.
|
1. Aşama: Ağ Bağlantısı ve HTTP Yanıtı Headers Alımı ve Response Objesinin Doğrulanması
Fetch API'nin tasarım felsefesi, ağ seviyesindeki başarıyı ( sunucuya ulaşmak ) uygulama seviyesindeki başarıdan ( doğru veriyi almak ) keskin bir çizgiyle ayırır.
Bu aşamada geliştiricinin en kritik görevi, Response objesi çözüldüğü anda onun içeriğini mantıksal bir süzgeçten geçirmektir.
fetch() tarafından döndürülen Promise'in çözülmesi (resolve), işlemin her zaman "olumlu" bittiği anlamına gelmez.
Sunucu size "Aradığınız dosya yok (404)" veya "Sunucumda bir arıza var (500)" dese bile, size bir Response Headers paketi gönderdiği için Promise başarıyla çözülür.
Bu noktada geliştirici, response.ok ( HTTP durumunun 200-299 arasında olup olmadığını kontrol eden Boolean değer) özelliğini manuel olarak denetlemek zorundadır.
Manuel Hata Fırlatma: Akışı YönlendirmekEğer response.ok değeri false ise, geliştirici throw new Error() ifadesini kullanarak asenkron akışı manuel olarak kesmelidir.
Bu bilinçli müdahale, asenkron akışı Promise zincirindeki başarı yolundan saptırıp .catch() bloğuna yönlendirir.
Böylece hem ağ hataları hem de HTTP hata kodları tek bir merkezi noktada, senkron kod disiplinine benzer bir netlikle yönetilebilir hale gelir.
Sonuç olarak, Fetch 1. Aşama kontrolü, uygulamanın dış dünyadan gelen yanıltıcı başarı mesajlarına karşı en önemli savunma kalkanıdır.
Bu disiplinli yaklaşım, veri ayrıştırma aşamasına sadece sağlıklı verilerin geçmesini garanti eder.
2. Aşama: Veri Okuma ve JSON Ayrıştırma Ham Veri Akışının (Stream) Nesneye Dönüşümü
Bu ikinci aşama, ağ el sıkışması bittikten ve HTTP başlıkları başarıyla onaylandıktan sonra başlar.
Ancak Fetch mimarisinde, başlıkların gelmiş olması verinin tamamının geldiği anlamına gelmez.
response.json() metodunun görevi, sunucudan hala akmaya devam edebilecek olan ham yanıt gövdesini okumak ve bu string formatındaki metni JavaScript'in anlayabileceği yerel bir veri yapısına parse etmektir.
Asenkron Zorunluluk ve PerformansAyrıştırma işlemi, özellikle gövde verisi büyükse yüksek işlemci gücü gerektirebilir.
JavaScript motorunun bu ağır ayrıştırma işlemini ana iş parçacığında yapması, kullanıcı arayüzünü donduracağı için mimari olarak asenkron tasarlanmıştır.
Bu nedenle response.json(), verinin tamamı inip başarıyla ayrıştırılana kadar beklemenizi gerektiren yeni bir Promise döndürür.
Hata Yönetimi: Sözdizimi KontrolüBu aşama, tamamen JSON Ayrıştırma Hatalarını ( Syntax Errors ) yönetir.
Ağ bağlantısı mükemmel olsa ve sunucu 200 OK döndürse bile, eğer sunucu yanlışlıkla eksik bir parantez veya hatalı biçimlendirilmiş bir metin gönderirse, bu ikinci Promise rejected durumuna geçer.
Geliştirici için bu durum, ağ hatasından ziyade bir veri bütünlüğü hatasıdır.
Özetlemek gerekirse, 2. Aşama, asenkron zincirin en hassas halkasıdır.
Geliştiricinin bu aşamayı bilinçli yönetmesi, uygulamanın bozuk verilerle çalışmasını engelleyerek veri güvenliğini ve çalışma zamanı kararlılığını sağlar.
Modern Kullanım: async/await ile Temiz Akış Fetch Süreçlerinin Senkron Görünümlü Yönetimi
async/await yapısı, JavaScript'in asenkron doğasını yönetmenin zirvesini temsil eder.
Bu yapı, Fetch API'sinin iki aşamalı Promise sürecinden kaynaklanan bilişsel yükü ortadan kaldırarak, asenkron kod yazmayı bir
"hikaye anlatıcılığına" dönüştürür.
Felsefe: Senkron Akışın Geri KazanılmasıGeleneksel Promise zincirlerinde ( .then() ), her adım bir sonrakine callback ile bağlanırken kod sağa doğru büyümeye meyleder.
async/await ise bu karmaşıklığı dikey bir düzleme çeker.
Kodun mantığını yukarıdan aşağıya okuyormuş hissi vererek, asenkron işlemleri senkron bir mantık akışıyla yönetmemize olanak tanır.
Bu, sadece bir söz dizimi değişikliği değil, aynı zamanda kod kalitesini artıran bir mimari sadeleşmedir.
Uygulama: İki Await ile Tam DenetimFetch'in iki aşamalı asenkron süreci, modern mimaride sadece iki yalın await ifadesiyle disipline edilir:
- Birinci await (fetch): Ağ bağlantısının kurulmasını ve Response objesinin (headers) yakalanmasını sağlar.
- İkinci await (json): Gelen ham verinin belleğe alınıp JavaScript objesine dönüştürülmesini bekler.
Bu ardışık kullanım, arka planda otomatik olarak kurulan bir Promise zinciri demektir; ancak geliştirici için bu süreç sadece satır satır ilerleyen, anlaşılır bir iş akışıdır.
Hata Yönetimi: try...catch Güvenlik ÇemberiModern akışın en büyük avantajı hata yönetimidir; try...catch blokları sayesinde, hem ağ kopuklukları hem de hatalı JSON ayrıştırma işlemleri aynı güvenlik çemberi içinde yakalanır.
Bir Promise reddedildiğinde, bu durum bir istisna olarak fırlatılır ve senkron hata yönetimi disipliniyle sezgisel bir şekilde işlenir.
Sonuç olarak, async/await kullanımı, asenkron süreçlerin karmaşıklığını gizleyerek yazılımın okunabilirliğini ve sürdürülebilirliğini en üst seviyeye taşır.
Bu modern akış, günümüz web uygulamalarının veri alışverişi katmanındaki altın standarttır.
Basit API Çağrısı Örneği async/await
async function veriCekme(url) {
try {
// 1. Await: Ağ bağlantısını ve HTTP yanıtını bekler (İlk Promise)
const response = await fetch(url);
// Hata Kontrolü: 404 veya 500 gibi durum kodları hata fırlatmaz, manuel kontrol gerekir.
if (!response.ok) {
throw new Error(`HTTP Hata Durumu: ${response.status}`);
}
// 2. Await: JSON verisinin okunmasını ve JavaScript objesine ayrıştırılmasını bekler (İkinci Promise)
const veri = await response.json();
return veri; // Nihai JavaScript objesini döndür
} catch (hata) {
// Ağ hataları (bağlantı kesintisi) ve JSON ayrıştırma hataları burada yakalanır.
console.error("Veri çekilemedi:", hata.message);
throw hata; // Hatanın yayılmasını sağlar.
}
}
// Kullanım:
veriCekme("https://api.ornek.com/kullanici").then(kullanici => {
console.log("Kullanıcı Adı:", kullanici.ad);
});
JSON Yönetimi: Dil Dışı Veri Formatı Evrensel Veri Sözleşmesi ve Çift Yönlü Dönüşüm
JSON, modern dijital ekosistemin merkezi veri alışveriş formatıdır. Adında "JavaScript" ibaresi yer alsa da, JSON teknik olarak dilden bağımsız bir metin formatıdır.
Bu evrensellik, JSON'u Java, Python, Go veya JavaScript kullanan farklı sistemlerin birbirleriyle anlaşabilmesini sağlayan ortak bir "diplomatik dil" haline getirir.
Tanım ve Felsefe: Saf Metin DisipliniJSON, JavaScript'in Nesne ve Dizi söz diziminden ilham alan ( {} ve [] ) ancak katı kuralları olan bir saf metin formatıdır.
Sadece temel veri tiplerini barındırabilir; fonksiyonlar veya karmaşık prototipler JSON içinde taşınamaz.
JSON'un varlık felsefesi, bellekteki canlı ve karmaşık objeleri dondurarak, ağ üzerinden güvenle iletilebilecek hafif bir forma dönüştürmektir.
Serileştirme ve Ayrıştırma: Yaşam DöngüsüAPI entegrasyonu, verinin bir "paket" haline getirilmesi ve ulaştığı yerde bu paketin açılması sürecidir:
- Serileştirme (Serialization) - Gönderme: JSON.stringify(obj) metodu kullanılır. Canlı bir JS objesi, ağ katmanının taşıyabileceği düz bir metne dönüştürülür. Objeler ağa çıkmadan önce bu "paketleme" işleminden geçmek zorundadır.
- Ayrıştırma (Deserialization) - Alma: JSON.parse(string) veya asenkron response.json() metodu kullanılır. Ağdan gelen "soğuk" metin, tekrar JavaScript'in yerel ve kullanılabilir objelerine dönüştürülerek canlandırılır.
Özet olarak, JSON, sadece bir veri formatı değil; modern yazılım mimarisinin en güvenilir sözleşme aracıdır.
Bu çeviri sürecini hatasız yönetmek, veri bütünlüğünü korumanın ve diller arası sorunsuz iletişim kurmanın temel şartıdır.
Asenkron Akışta Güvenilirlik: Hata Kurtarma Stratejileri Sistem Dayanıklılığı (Resilience)
Asenkron akışlar ve API iletişimleri, doğası gereği kararsızdır.
Ağ gecikmeleri, sunucu aşırı yüklenmeleri veya mikro saniyelik kesintiler gibi geçici hatalar dijital ekosistemin kaçınılmaz bir parçasıdır.
Bu hataları görmezden gelmek, kullanıcı deneyiminde ani kesintilere ve iş kritik süreçlerde telafisi imkansız veri kayıplarına yol açar.
Modern bir uygulamanın güvenilirliği, yalnızca başarılı istekleri işleme hızıyla değil, aynı zamanda başarısızlıkları ne kadar zarif ve akıllıca yönettiğiyle ölçülür.
Güvenilirlik, artık bir lüks değil, modern ve ölçeklenebilir sistemler için temel bir mühendislik zorunluluğudur.
Dayanıklılık (Resilience) Tasarım DesenleriSistem dayanıklılığını artırmak için kullanılan stratejiler, kodun hata anında pes etmesi yerine alternatif yollar bulmasını sağlar.
Bu bölüm, asenkron akışta dayanıklılığı artırmak için endüstri standartı haline gelmiş dört kritik hata kurtarma stratejisini incelemektedir.
- Retry (Yeniden Deneme): Hata anında vazgeçmeyip, belirli aralıklarla işlemi tekrar başlatma disiplini.
- Fallback (B Planı): Ana işlem başarısız olduğunda, kullanıcıya sunulacak yedek veya statik bir veri yolu.
- Timeout (Zaman Aşımı): Sonsuz beklemeleri engelleyerek sistem kaynaklarını koruma mekanizması.
- Circuit Breaker (Devre Kesici): Sürekli hata veren bir servise giden yolu kapatarak sistemin çökmesini önleme stratejisi.
Sonuç olarak, asenkron dünyada Hata Kurtarma Stratejileri, yazılımın hayatta kalma içgüdüsüdür.
Bu stratejileri modüler bir şekilde koda entegre etmek, sistemi her türlü dışsal dalgalanmaya karşı korunaklı bir kaleye dönüştürür.
Yeniden Deneme (Retry Pattern) Strateji 1: Kendi Kendini Onaran (Self-Healing) Sistemler
Asenkron programlamada bir API çağrısının başarısız olması, sistemin kalıcı olarak çöktüğü anlamına gelmez.
Geçici Hata ( Transient Error ) olarak adlandırılan kısa süreli ağ tıkanıklıkları, sunucu tarafındaki anlık kaynak yoğunlukları veya 503 gibi durumlar, saniyeler içinde kendiliğinden düzelme potansiyeli taşır.
Retry Pattern, bu öngörüyü temel alarak, uygulamayı hemen başarısız ilan etmek yerine işlemi otomatik olarak tekrarlayan proaktif bir disiplindir.
Bu stratejinin temel amacı, uygulamanın kullanıcı müdahalesine gerek duymadan hataları arka planda sessizce çözmesini sağlamaktır.
Bu yetenek, modern yazılım mimarisinde kendi kendini onarma kapasitesi olarak tanımlanır ve sistemin genel erişilebilirliğini radikal bir şekilde artırır.
Kısıtlamalar ve Yan Etki Riski: Fırtına EtkisiYeniden deneme mekanizması kağıt üzerinde kusursuz görünse de, yanlış yapılandırıldığında bir felaket senaryosuna dönüşebilir.
Örneğin: 1 saniye arayla sabit 5 kez deneme yapan binlerce istemci, zaten aşırı yük altında olan bir sunucuya aynı anda "saldırarak" sunucunun toparlanma şansını tamamen yok edebilir.
Bu durum, istemcilerin istemeden bir DoS ( Denial of Service ) atağı gerçekleştirmesine neden olur ve sistemin kurtulma süresini uzatır.
Bu riski yönetmek için; denemeler arasına değişken zamanlar eklemek veya deneme sayısını stratejik olarak kısıtlamak gibi ileri seviye kontrol mekanizmaları zorunlu hale gelir.
Sonuç olarak, Retry Pattern, asenkron akışlarda dayanıklılığı artıran en temel araçtır.
Ancak bu aracı kullanırken sunucu üzerindeki yükü hesaba katmak, sistemin sadece kendi başarısını değil, bütünsel sağlığını da korumanın anahtarıdır.
Üstel Geri Çekilme (Exponential Backoff) Gelişmiş Yeniden Deneme ve Sunucu Koruma Stratejisi
Basit yeniden deneme döngülerinin yarattığı riskleri ortadan kaldıran ve sistem dayanıklılığını maksimuma taşıyan yöntem, Üstel Geri Çekilme stratejisidir.
Bu strateji, ardışık başarısızlıklar sonrasında beklenen zaman aralığını sabit tutmak yerine, her denemede üssel olarak artırarak sunucunun üzerindeki baskıyı kademeli olarak azaltır.
Matematiksel Artış ve Kurtarma ZamanıÜssel Artış: Bekleme sürelerinin her adımda katlanarak artması ( 1s, 2s, 4s, 8s... gibi), sunucuya içine düştüğü darboğazdan çıkması ve kaynaklarını yeniden organize etmesi için gereken kritik zaman dilimini tanır.
Sabit beklemeler sunucuyu sürekli döverken, üstel geri çekilme sisteme "nefes alma alanı" açar.
Jitter: Thundering Herd Probleminin ÇözümüRastgele Değer (Jitter): Eğer tüm istemciler ( binlerce kullanıcı ) aynı matematiksel algoritmayı kullanarak tam olarak aynı saniyede yeniden deneme yaparsa, sunucuda yeni ve daha büyük bir çarpışma dalgası oluşur.
Buna literatürde Thundering Herd problemi denir.
Jitter, hesaplanan üstel süreye küçük, rastgele bir sapma ekleyerek istemcilerin deneme zamanlarını zamana yayar ve sunucu yükünü homojenize eder.
Faydası: Bu kontrollü ve bilimsel yaklaşım, hem uygulamanın geçici hatalardan kurtulma oranını yükseltir hem de sistemin en zayıf anında hedef sunucunun tamamen çökmesini engelleyerek hızlıca rehabilitasyonunu garanti altına alır.
Özet olarak, Üstel Geri Çekilme, sadece bir kod bloğu değil, olgun bir mühendislik nezaketidir.
Sistemin kendi başarısı kadar ekosistemin sürdürülebilirliğini de düşünerek, kriz anlarında kaosu matematiksel bir düzene sokar.
|
Kontrol Mekanizması
|
Açıklama
|
Neden Kritik?
|
|---|---|---|
|
Hata Sınıflandırması
|
Yeniden denemenin yalnızca geçici hatalar için tetiklenmesi
gerekir.
|
404 Not Found
veya 401 Unauthorized gibi kalıcı hataları
tekrar
denemek
kaynak israfıdır.
Genellikle sadece 5xx ve ağ ile ilgili zaman aşımı/bağlantı hataları denenir. |
|
Maksimum Deneme Limiti
|
İsteğin sonsuza dek döngüye girmesini önlemek için
belirlenen
maksimum
deneme sayısı.
|
Limitin aşılması durumunda uygulama, işlemi kesin olarak
başarısız
ilan
etmeli ve hatayı üst katmana bildirmelidir.
|
|
Bekleme Stratejisi
|
Basit bekleme yerine Üstel
Geri Çekilme veya
Rastgele
Gecikme kullanılması.
|
Sunucunun aşırı yüklenmesini engeller ve tüm istemcilerin
aynı
anda
saldırmasını ( thundering herd ) önler, dağıtık sistemlerde
çarpışma riskini azaltır.
|
|
Timeout Yönetimi
|
Yeniden deneme döngüsünün, genel bir işlem zaman aşımı (
overall
timeout )
içinde kalması gerekir.
|
Kullanıcının bekleme süresi, tüm denemeler dahil olmak
üzere, kabul edilebilir bir sınırın altında tutulmalıdır.
|
Zaman Aşımı (Timeout) Strateji 2: Belirsiz Beklemelerin Deterministik İptali
Asenkron programlamanın en sinsi tehlikesi, bir işlemin yanıtının gelmeyeceği kesinleştiği halde süresiz olarak sistem kaynaklarını meşgul etmeye devam etmesidir.
Ağ tıkanıklıkları veya sunucu kilitlenmeleri gibi durumlarda, uygulamanın bu işlemi "umutla" beklemesi, bellekte sızıntılara ve bağlantı havuzunun dolmasına neden olur.
Zaman Aşımı, asenkron bir göreve kesin bir "son kullanma tarihi" atayarak bu belirsizliği ortadan kaldıran temel güvenlik mekanizmasıdır.
Timeout mekanizması, asenkron görevin başlangıcından itibaren işleyen bir kronometre gibi çalışır.
Belirlenen süre aşıldığında, işlem teknik olarak devam ediyor olsa bile uygulama katmanında bu bağ koptuğu kabul edilir ve görev zorla rejected durumuna çekilir.
Kullanıcı Deneyimi (UX) ve Sabır EşiğiZaman aşımı yalnızca sistem stabilitesi için değil, Kullanıcı Deneyimi için de hayati bir disiplindir.
Bir kullanıcının sonsuza kadar dönen bir yükleme simgesini izlemesi, sistemin çökmüş olduğu algısını yaratır.
Gelişmiş mimarilerde gecikme süresi, kullanıcının sabır eşiği (genellikle 3-10 saniye arası) dikkate alınarak belirlenir.
Timeout gerçekleştiğinde uygulama sessiz kalmaz; kullanıcıya şeffaf bir geri bildirim sunar ( "Bağlantı zaman aşımına uğradı, lütfen tekrar deneyiniz" ).
Bu, belirsizliğin yarattığı kaygıyı ortadan kaldırarak kontrolün kullanıcıda kalmasını sağlar.
Sonuç olarak, Zaman Aşımı stratejisi, asenkron programlamanın "dur-kalk" kontrolüdür.
Sonsuz beklemeleri sonlandırarak hem sunucu üzerindeki atıl yükü azaltır hem de sistemin her zaman cevap verebilir kalmasını garanti eder.
Modern İptal Mekanizmaları AbortController ve İptal Sözleşmesi (Cancellation Contract)
Geleneksel JavaScript ekosisteminde asenkron bir işlemi iptal etmek, genellikle karmaşık ve hata eğilimli manuel çözümler gerektiriyordu.
Eski yöntemler çoğu zaman Promise'i gerçekten durduramaz, sadece sonucunu görmezden gelirdi.
Bu durum, işlem iptal edilmiş gibi görünse de arka planda gereksiz ağ trafiği ve işlemci yükünün devam etmesine, dolayısıyla kaynak israfına yol açardı.
Modern Çözüm: AbortController ArayüzüModern asenkron programlama, bu yapısal sorunu AbortController arayüzü ile aşmıştır.
Bu yapı, uzun süreli ve potansiyel olarak askıda kalabilecek görevler için merkezi bir iptal sözleşmesi tanımlar.
AbortController, sadece bir zaman aşımı aracı değil; tüm iptal ve temizlik operasyonlarını koordine eden akıllı bir sinyal mekanizmasıdır.
Mimari Rol: Sinyal Tabanlı İletişim HattıAbortController'ın temel mimari rolü, asenkron işlemler arasında temiz bir iletişim hattı kurmaktır.
Controller tarafından üretilen signal nesnesi, asenkron görevin ( bir fetch isteği gibi ) içine bir bağımlılık olarak enjekte edilir, bu noktadan itibaren görev "dinleme" moduna geçer.
controller.abort() metodu çağrıldığı anda, enjekte edilen sinyal tüm dinleyicilere "dur" talimatı gönderir.
Bu sinyal, bir zaman aşımı sayacından gelebileceği gibi, kullanıcının sayfadan ayrılması veya bir "İptal" butonuna basması gibi
kullanıcı etkileşimli bir kaynaktan da tetiklenebilir.
Sonuç olarak, AbortController, asenkron dünyada "başıboş" kalan süreçleri engelleyen en güçlü güvenlik subabıdır.
Bu mekanizma, uygulamanın bellek sızıntılarından korunmasını, ağ trafiğinin optimize edilmesini ve kullanıcı arayüzünün her zaman cevap verebilir kalmasını garanti eder.
|
Özellik
|
AbortController (Modern)
|
Manuel setTimeout (Geleneksel)
|
|---|---|---|
|
İptal Düzeyi
|
Doğrudan ağ isteği/Promise'in kendisini iptal eder.
|
Promise çözüldükten sonra sonuçlarının işlenmesini
engeller,
asıl
işlem
arka planda çalışmaya devam edebilir.
|
|
Sinyal Kaynağı
|
Tek bir sinyal objesi birden fazla fetch isteğini iptal
edebilir.
|
Her zaman aşımı için ayrı bir ID yönetimi gerekir.
|
|
Hata Türü
|
Standart AbortError fırlatır, ayrımı kolaydır.
|
Genellikle manuel olarak fırlatılan özel Error objeleri
yönetimi
zorlaştırır.
|
|
Mekanizması
|
Açıklama
|
Neden Kritik?
|
|---|---|---|
|
Kritik Araç
|
AbortController
kullanımı.
|
Geleneksel setTimeout tabanlı manuel iptallere göre daha
temiz, Promise
tabanlı ve standart bir asenkron iptal mekanizması sağlar.
|
|
Süre Yönetimi
|
Zaman aşımı sürelerinin katmanlara göre belirlenmesi.
|
Dış katmandaki genel bir işlem zaman aşımı, iç
katmandaki zaman
aşımından farklı olmalıdır.
Çoğu Web API için 5-15 saniye aralığı yaygındır. |
|
Hata Türü
|
Zaman aşımı durumunda yakalanan hatanın türü
(AbortError).
|
AbortError hatasını, ağ hatası veya sunucu hatasından
ayırmak,
uygulamanın yeniden deneme stratejisini doğru yönetmesi için esastır
( Zaman aşımı genellikle yeniden denenebilir bir hata olarak kabul edilir ). |
|
Sistem Kaynağı
|
Açık ağ bağlantılarının ve soketlerin serbest
bırakılması.
|
Uzun süreli bekleme durumları, sunucu veya istemcideki
soket
havuzlarını gereksiz yere doldurarak yeni bağlantıları engeller ve sistemin genel
performansını
düşürür.
|
Devre Kesici (Circuit Breaker Pattern) Strateji 3: Asenkron Akışlarda Akıllı Sigorta Mekanizması
Devre Kesici, adını ve çalışma mantığını elektrik tesisatlarındaki fiziksel sigortalardan alır.
Bir elektrik devresinde aşırı yük veya kısa devre oluştuğunda sigorta atarak akımı keser ve tüm sistemin yanmasını engeller.
Asenkron yazılım mimarisinde de Devre Kesici; uzak bir hizmetin ( API, veri tabanı veya mikro servis ) sürekli başarısız olduğunu algıladığında, o hizmete yönelik tüm istek trafiğini kısa devre yaparak derhal durdurur.
Stratejik Ayrım: Neden Retry Pattern Yetersiz Kalır?Yeniden Deneme, anlık ağ dalgalanmaları gibi geçici hatalar için mükemmel bir çözümdür.
Ancak karşı servis tamamen çökmüşse veya kalıcı bir donanım arızası yaşıyorsa, ısrarla yeniden denemek sorunu çözmek yerine daha da derinleştirir.
Sürekli yapılan denemeler, zaten nefes alamayan bir servise ek yük bindirerek onun "iyileşme süresini" sabote eder.
Devre Kesici, bu noktada devreye girerek sorunun geçici bir hıçkırıktan ziyade yapısal bir kriz olduğuna karar verir.
İstemci tarafında sanal bir "güvenlik duvarı" örerek, başarısız olacağı kesin olan istekleri henüz ağa çıkmadan reddeder ve bu, sistem kaynaklarını ( bellek, bağlantı havuzu ) boşa harcamayı engeller.
Durum Yönetimi (States)Devre Kesici üç temel durumda çalışır:
- Kapalı (Closed): Her şey normaldir, istekler iletilir.
- Açık (Open): Hata eşiği aşılmıştır, istekler engellenir ve anında hata döndürülür.
- Yarı-Açık (Half-Open): Belirli bir süre sonra sistemin düzelip düzelmediğini anlamak için kısıtlı sayıda deneme isteğine izin verilir.
Sonuç olarak, Circuit Breaker stratejisi, asenkron sistemlerde zincirleme çökmeleri engelleyen en olgun savunma mimarisidir.
Sistemin hatalara karşı körü körüne direnç göstermesi yerine, stratejik bir geri çekilme yaparak bütünsel sağlığı korumasını sağlar.
Üç Durum Modeli ve Stratejik Fonksiyonlar Dinamik Durum Makinesi (State Machine) Mimarisi
Devre Kesici'nin asıl gücü, statik bir hata kontrol mekanizması olmasından değil; hizmetin anlık tepkilerine göre kendi davranışını saniyeler içinde değiştirebilen akıllı bir Durum Makinesi olmasından gelir.
Bu yapı, sistemi sadece "açık" veya "kapalı" tutmaz; arızanın derinliğini analiz ederek sistemin en güvenli modda çalışmasını sağlar.
Temel Mekanizma: Durumların Fonksiyonel GörevleriDevre Kesici, asenkron veri akışını yönetirken sistemi sürekli olarak şu üç kritik durumdan birinde tutar ve geçişleri matematiksel eşiklere göre otomatik yönetir:
-
Kapalı (Closed): Sistem sağlıklıdır ve tüm asenkron
istekler
sunucuya iletilir. Bu durumda devre, ardışık hataları sayan bir
pasif gözlemci rolündedir. Hata eşiği aşılmadığı sürece akış kesilmez. - Açık (Open): Kritik hata eşiği aşılmıştır. Devre, "sigorta atmış" gibi davranarak tüm istekleri ağa çıkmadan anında reddeder. Amacı, çökmüş olan servise nefes aldırmak ve istemci tarafında kaynak israfını önlemektir.
- Yarı-Açık (Half-Open): Soğuma süresi bitmiştir. Sistem, servisin düzelip düzelmediğini anlamak için çok düşük hacimli bir deneme trafiğine izin verir. Eğer denemeler başarılıysa devre kapanır; başarısızsa tekrar "Açık" moda döner.
Bu geçişler, rastgele değil, belirli bir zaman aşımı ve hata oranı parametrelerine bağlıdır. Bu disiplin, sistemin "panik yapmasını" engeller ve asenkron trafiği veri tutarlılığı ile sistem sağlığı arasında optimize eder.
Tüm bunların ışığında, Üç Durum Modeli, asenkron mimarilerin bel kemiğidir.
Bu yapı sayesinde sistem, arızalar karşısında körü körüne deneme yapmak yerine, durumsal farkındalık kazanarak hem kendini hem de bağlı olduğu servisleri koruma altına alır.
Kapalı Durum (Closed) Mekanizması Aktif İzleme ve Sağlıklı Akışın Korunması
Kapalı Durum (Closed), asenkron sistemin sağlıklı, stabil ve her şeyin yolunda olduğu varsayılan temel çalışma modudur.
Bu aşamada sistem, "herhangi bir arıza yok" kabulüyle hareket eder ve asenkron veri akışını en yüksek performansla yürütür.
Normal Akışın Sürdürülmesi: Bu modda istemci tarafından gelen tüm asenkron talepler, herhangi bir filtreleme veya engellemeye maruz kalmadan doğrudan hedef servise iletilir.
Bu, sistemin düşük gecikme süresi ile optimal performansta çalışmasını garanti eder.
Arka Plan Disiplini: Aktif İzlemeKapalı durumda devre "pasif" bir beklemede değildir.
Aksine, arka planda son derece titiz bir aktif izleme süreci yürütür.
Belirlenmiş bir zaman penceresi içinde gerçekleşen tüm başarısızlıkları, zaman aşımlarını ve hatalı yanıtları sürekli olarak kayıt altına alır.
Korumanın Başlangıcı: Hata Eşiği AnaliziKapalı durum, hataların "tolere edilebilir" seviyede kaldığı sürece korunur.
Ancak, başarısızlık oranı önceden tanımlanmış hata eşiğini geçtiği anda sistem alarm verir.
Örneğin: Son 20 istekten %50'si başarısız olduysa, Devre Kesici servisin kritik bir kriz yaşadığına hükmeder ve saniyeler içinde Açık Duruma geçiş yapar.
Bu anlık karar, koruyucu mimarinin sistem genelini bir zincirleme çöküşten kurtardığı ilk savunma hamlesidir.
Sonuç olarak, Kapalı Durum, sadece verinin aktığı bir kanal değil; her an her şeye hazırlıklı olan
stratejik bir gözlem kulesidir.
Bu evrede yapılan doğru ölçümler, kriz anında sistemin vereceği tepkinin isabet oranını belirler.
Açık Durum (Open) Mekanizması Kritik Arıza Modu ve Servis Koruma Kalkanı
Açık Durum (Open), Devre Kesici sisteminin en agresif savunma evresidir.
Bu durum, hedef servisin artık talepleri karşılayamayacak düzeyde kritik bir arıza moduna girdiğini ve acilen korunması gerektiğini simgeler. Sistem, bu modda "iletişimi keserek kurtar" mantığıyla hareket eder.
Fail Fast (Hızlı Hata) PrensibiAçık durumda, Devre Kesici gelen tüm yeni asenkron talepleri kapıda derhal engeller.
İsteklerin ağ katmanına çıkmasına ve hedef servisi yormasına izin verilmez.
Bunun yerine sistem, istemciye milisaniyeler içinde "Hizmet Şu An Kullanılamıyor" yanıtı fırlatır.
Bu Fail Fast yaklaşımı, istemcinin boş yere beklemesini engellerken, zaten çökmüş olan servisin üzerindeki yük baskısını tamamen kaldırır.
Servis Kurtarma Penceresi ve SoğumaSistem bu koruma kalkanını devreye aldığı anda bir bekleme süresi (timeout period) başlatır.
Bu süre, teknik bir "soğuma dönemi"dir ve genellikle 30 saniye ile birkaç dakika arasında değişen bu pencere, arızalı servise; kilitlenmiş bağlantıları serbest bırakması, bellek sızıntılarını temizlemesi veya yeniden başlatılması için ihtiyaç duyduğu stratejik zamanı tanır.
Zorunlu Geçiş: Deneme HazırlığıBekleme süresi sona erdiğinde, Açık Durum'un pasif koruma görevi tamamlanmış olur.
Sistem, servisin hala arızalı olup olmadığını "varsaymak" yerine, durumu bizzat test etmek için otomatik ve zorunlu olarak Yarı-Açık duruma geçer.
Bu geçiş, sistemin normal operasyona dönme çabasının ilk kontrollü adımıdır.
Sonuç olarak, Açık Durum, asenkron sistemin panik yapmadan "kontrollü bir duruş" sergilediği evredir.
Gereksiz trafiği keserek hem istemciyi hem sunucuyu koruyan bu mod, mimari dayanıklılığın en somut göstergesidir.
Yarı-Açık Durum (Half-Open) Mekanizması Test ve Doğrulama Modu: Sistemin İyimser Denemesi
Yarı-Açık Durum, Devre Kesici mimarisinin en "akıllı" evresidir.
Bu durum, sistemin test ve doğrulama modunu temsil eder.
Açık durumdaki mutlak izolasyonun ardından, sistemin iyimser bir yaklaşımla servisin düzelmiş olabileceğini varsaydığı ve bu varsayımı minimal riskle kanıtlamaya çalıştığı aşamadır.
Tek Test İzni ve Sınırlı ErişimBu aşamada devre, kapılarını tamamen açmaz, aksine, gelen taleplerden sadece bir sonraki tek bir test isteğinin hedef servise ulaşmasına izin verir.
Bu istek, literatürde Sonda olarak adlandırılır.
Amacı, servisi tekrar aşırı yüke boğmadan, sadece "orada kimse var mı ve sağlıklı mı?" sorusuna yanıt aramaktır.
Kader Anı: Kesin Karar MekanizmasıGönderilen bu test isteğinin sonucu, tüm sistemin asenkron geleceğini belirleyen bir kader anıdır:
- Başarı Durumu (Success): Eğer test isteği başarıyla tamamlanırsa, servis iyileşmiş kabul edilir. Devre Kesici derhal Kapalı Duruma geri döner, sayaçları sıfırlar ve normal trafik akışını başlatır.
- Başarısızlık Durumu (Failure): Eğer test isteği hata alırsa, bu servisin henüz rehabilitasyon sürecini tamamlamadığı anlamına gelir. Devre Kesici zaman kaybetmeden tekrar Açık Duruma döner ve yeni, genellikle daha uzun bir soğuma süresi başlatır.
Sonuç olarak, Yarı-Açık Durum, asenkron sistemlerin körü körüne risk almasını engelleyen bir mantık süzgecidir.
Bu "sonda" stratejisi sayesinde sistem, hatalı servisleri yormadan iyileşme anını hassas bir doğrulukla saptayabilir.
|
Kontrol Mekanizması
|
Açıklama
|
Neden Kritik?
|
|---|---|---|
|
Hata Eşiği (Threshold)
|
Devre Kesiciyi Açık duruma geçirecek başarısızlık sayısı
veya
oranı.
|
Bu eşik, sistemin hassasiyetini belirler.
Çok düşük bir eşik, gereksiz atmalara neden olur; çok yüksek bir eşik ise korumayı geciktirir. |
|
Bekleme Süresi (Timeout)
|
Devre Açık durumdayken, Yarı-Açık duruma geçmeden önce
beklenmesi
gereken
süre.
|
Servise toparlanması için garanti edilmiş bir zaman dilimi
sunar;
süre,
kurtarma hedeflerine (RTO) göre belirlenir.
|
|
Test İsteği (Probe)
|
Yarı-Açık durumdayken gönderilen ve Devre Kesici'nin
durumunu
belirleyen tek
istek.
|
Servisin gerçekten kurtulup kurtulmadığını minimal yükle
kontrol eder;
başarısız olursa Devre Kesici kendini tekrar korumaya alır.
|
|
İstemci Yanıtı
|
Açık durumdayken istemciye sunulan yanıt.
|
İstemci, ağ isteği beklemek yerine, önbellekten veri
döndürebilir veya
varsayılan bir değerle kullanıcı deneyimini sürdürebilir.
|
İdempotans (Idempotency) Strateji 4: Yinelenen İsteklerde Veri Bütünlüğü Garantisi
İdempotans, matematik ve bilgisayar bilimlerinde bir operasyonun kaç kez uygulanırsa uygulansın, sonucun tek bir uygulama ile aynı olması prensibidir.
Asenkron API mimarilerinde bu kavram; bir sunucuya gönderilen veri yazma veya güncelleme isteğinin, ağ hataları nedeniyle istemci tarafından defalarca tekrarlansa bile sunucu tarafında sadece bir kez kalıcı değişiklik yaratacağını garanti eder , bu,
"bir kez ve sadece bir kez" işlem yapma idealinin teknik karşılığıdır.
Neden Zorunludur? Ağın "Karanlık Bölgesi"Önceki stratejiler ( Retry, Timeout ) istemci tarafındaki aksaklıkları yönetir.
Ancak, sunucunun işlemi başarıyla tamamlayıp yanıtı gönderdiği sırada ağın kopması durumunda büyük bir belirsizlik doğar.
İstemci yanıt alamadığı için işlemi "başarısız" sayıp Yeniden Deneme başlatır.
Eğer sistem idempotent değilse, sunucu bu ikinci isteği yepyeni bir talep sanarak işlemi mükerrer yapar; bu da finansal kayıplara veya veri kirliliğine yol açar.
Uygulama Mantığı: Benzersiz Anahtar (Idempotency Key)Bu strateji genellikle istemci tarafından oluşturulan benzersiz bir anahtar üzerinden yürütülür. Sunucu, bu anahtarı gördüğünde işlemi daha önce yapıp yapmadığını kontrol eder.
İşlem yapılmışsa, sonucu tekrar üretmek yerine eski sonucu döndürür.
Bu sayede hem ağ hataları tolere edilir hem de sistemin veri bütünlüğü korunmuş olur.
Özet olarak, İdempotans, asenkron iletişimde güvenin son kalesidir.
Diğer stratejiler hataları yönetirken, idempotans bu hataların yan etkilerini yönetir ve karmaşık ağ ortamlarında bile sistemin her zaman tutarlı kalmasını sağlar.
|
Kontrol Mekanizması
|
Açıklama
|
Neden Kritik?
|
|---|---|---|
|
Kullanım Alanı
|
Sadece durum değiştiren API çağrıları (POST, PATCH, DELETE).
|
GET ve OPTIONS gibi sadece veri
okuyan metotlar doğası
gereği
idempotenttir;
bu anahtara ihtiyaç duymaz.
|
|
Anahtar Üretimi
|
Anahtarın istemci tarafından rastgele ve benzersiz ( UUID )
üretilmesi
zorunludur.
|
Sunucu anahtarı üretirse, başarısız denemeler sonunda
anahtarın izi
kaybolabilir; kontrol istemcide olmalıdır.
|
|
TTL (Yaşam Süresi)
|
İdempotans anahtarlarının sunucuda saklanma süresinin
sınırlandırılması.
|
Sonsuza dek saklamak veritabanı yığılmasına yol açar;
genellikle 24
saat sonra
anahtar geçersizleştirilir.
|
|
Yanıt Tutarlılığı
|
Anahtar tekrar kullanıldığında, sunucunun ilk istekteki HTTP
durum
kodunu ve
yanıt gövdesini döndürmesi gerekir.
|
İstemcinin yeniden deneme mantığının beklediği yanıtı
almasını sağlar
ve
akışın bozulmasını önler.
|
🧭 Opsiyonel Okuma Notu
Bilgilendirme: Bu bölüm, konuların arka planına ve düşünsel temellerine daha derin bir bakış sunmak amacıyla hazırlanmıştır.
- Matematiksel, tarihsel ve felsefî içerikler isteğe bağlı olarak okunabilir.
- Her bölümün içerik seviyesi ve yoğunluğu farklılık gösterebilir.
- Temel düzey kullanıcılar için zorunlu değildir, ileri düzey okuma niteliğindedir.
Asenkron Programlama ve JSON ( Felsefi ve Tarihsel Açıklama )
Asenkron programlama,
bilgisayarlara hız kazandırmaktan çok,
bekleme kavramını yönetebilmek
için ortaya çıktı.
Çünkü gerçek dünyada her şey aynı anda sonuçlanmaz.
Bu bölümde,
kodun ne yaptığından ziyade,
neden sırayla çalışmak zorunda olmadığını,
zaman, veri ve iletişim kavramları üzerinden
daha düşünsel bir çerçevede ele alacağız.
Kavramsal Temel: Senkron ve Asenkron Felsefesi Zihinsel Model
Programlamanın kontrol akışı, temel olarak Senkron ve Asenkron olmak üzere iki zıt felsefi prensibe dayanır.
Bu prensipler, bir uygulamanın sadece işlem yapma kapasitesini değil, dış dünyaya karşı gösterdiği tepkiselliği ve sistem kaynaklarını ne kadar adil paylaştığını doğrudan belirleyen mimari köşe taşlarıdır.
Mimari Tercih: Öngörülebilirlik vs. VerimlilikSenkron ve asenkron arasındaki seçim, bir uygulamanın çevresiyle ( kullanıcı girdisi, ağ paketleri, disk I/O işlemleri ) nasıl etkileşim kuracağına dair yapılan en temel mimari tercihtir.
- Senkron Yapı: Katı bir öngörülebilirlik ve sıra garantisi sunar. Kod, bir komut bitmeden diğerine geçmez; bu durum mantıksal takibi kolaylaştırsa da zaman alan işlemlerde sistemin "donmasına" yol açar.
- Asenkron Yapı: Maksimum verimlilik ve dinamik kaynak paylaşımı üzerine kuruludur. Görevlerin tamamlanma sırasından ziyade, sistemin boşta kalmamasını ve her an yeni bir talebe yanıt verebilmesini hedefler.
Asenkron programlama, aslında insan-makine etkileşimindeki doğallığı ve gerçek hayattaki çoklu görev mantığını taklit eder.
Tıpkı bir insanın bir yemeğin pişmesini ocağın başında hiçbir şey yapmadan beklemek yerine, o sırada sofrayı kurabilmesi gibi; bir program da uzun süren bir ağ isteğini arka plana atarak kendini kilitlemez.
Bu bloklamayan yaklaşım, modern kullanıcı deneyimi için bir tercih değil, mutlak bir zorunluluktur.
Kullanıcının bir butona tıkladığında cevabı beklerken ekranın donması, senkron felsefenin modern web standartlarındaki en büyük handikapıdır.
Asenkron yapı, bu engeli aşarak akışkan ve yaşayan arayüzler inşa etmemizi sağlar.
Sonuç olarak, Senkron ve Asenkron ayrımı sadece bir kod yazım stili değildir; sistemin zamanı ve dikkati nasıl yönettiğine dair bir
stratejik karardır.
Bu felsefeyi kavramak, karmaşık asenkron yapıları bir yük olarak değil, kullanıcı memnuniyeti için bir araç olarak görmemizi sağlar.
Senkron (Synchronous): Sıralı ve Bloklayıcı Yürütme Mutlak Bağımlılık ve Zamanın Durdurulması
Senkron programlama, komutların tıpkı bir domino taşları dizisi gibi, sarsılmaz bir hiyerarşi ve mutlak bir sırayla yürütülmesidir.
Bu felsefede her işlem, bir önceki işlemin tam olarak bitişine göbekten bağlıdır.
Kodun ikinci satırı, birinci satır işini bitirip "sıra sende" demeden asla nefes almaz.
Bu durum, mantıksal bir doğrusal düzen yaratarak kodun takibini ve hata ayıklamasını kolaylaştırsa da, modern web'in dinamik yapısında ağır bir bedel ödetir.
Kritik Dezavantaj: Bloklama (Blocking) MekanizmasıSenkron yapının en büyük handikapı, bloklayıcı doğasıdır.
Program akışı, zaman alıcı bir işlemle ( devasa bir dosyanın okunması veya ağır bir ağ sorgusu gibi ) karşılaştığında, o işlem tamamlanana kadar tüm CPU gücünü ve yürütme hattını o noktada kilitler.
Bir web uygulamasında bu durum felaketle sonuçlanır: Tarayıcı, sunucudan yanıt gelene kadar Kullanıcı Arayüzü güncellemelerini durdurur.
Kullanıcı, farenin hareket etmediği, butonların tepki vermediği ve sayfanın adeta "can çekiştiği" bir donma anı ile karşı karşıya kalır.
Senkron felsefe, basitliği uğruna tepkiselliği feda eder.
Özetlemek gerekirse, Senkron yapı, küçük ve anlık işlemler için ideal bir güven limanı olsa da, modern web'in çok görevli dünyasında sistemin önündeki en büyük engeldir ve zamanın durduğu bu noktada, asenkron yapının özgürleştirici etkisi devreye girer.
Asenkron (Asynchronous): Paralel ve Bloklamayan Akış Zamanın Verimli Kullanımı ve Delege Etme Sanatı
Asenkron programlama, bir görevi başlattıktan sonra onun bitişini bir nöbetçi gibi beklemeden, programın bir sonraki komuta hemen geçebilmesi felsefesidir.
Bu modelde kod, zaman alacak olan işlemi ( I/O , ağ isteği, veritabanı sorgusu ) başlatır ve kontrolü hemen geri alır. Uzun süreli görevler arka plana devredilirken, ana program akışı sanki hiçbir engel yokmuş gibi akmaya devam eder.
Felsefe: Bloklamayan (Non-Blocking) MimariAsenkronluğun kalbi, bloklamayan yapısında atar.
Senkron sistemlerin aksine, işlemci bir ağ isteğinden yanıt gelmesini beklerken atıl kalmaz; diğer kullanıcı etkileşimlerini işlemeye devam eder.
İşlem tamamlandığında, sistem bir "fısıltı" gibi sonucu Promise veya callback mekanizmasıyla ana programa bildirir.
Bu, sistem kaynaklarının saniyelerle değil, milisaniyelerle ölçülen bir hassasiyetle yönetilmesini sağlar.
Stratejik Avantaj: Duyarlı (Responsive) DeneyimBu felsefe; gecikmeli işlemlerin, ağ dalgalanmalarının ve büyük veri transferlerinin uygulamanın "yaşamsal fonksiyonlarını" etkilemesini engeller.
Asenkronluk sayesinde, bir dosya inerken kullanıcı hala menülerde gezinebilir, bir form gönderilirken sayfa animasyonları akmaya devam eder.
Günümüzün duyarlı uygulamalarında asenkronluk bir seçenek değil, uygulamanın nefes almasını sağlayan ana borudur.
Kullanıcıya "sistem çalışıyor" hissini veren şey, arka planda dönen karmaşık asenkron çarkların sessizce ve ana akışı sarsmadan dönmesidir.
Özetle, asenkron felsefe, programın kontrolünü tek bir işin tekeline vermeyi reddeder.
Zamanı paralel işleme mantığıyla bükerek, işlemci gücünü en çok ihtiyaç duyulan yere, yani kullanıcı etkileşimine odaklı tutar.
JavaScript'in Asenkron Mimarisi Mekanizmaların İş Birliği
JavaScript, doğası gereği tek iş parçacıklı bir dildir.
Bu, motorun aynı anda yalnızca tek bir kod satırını yürütebileceği, tek bir Call Stack'e sahip olduğu anlamına gelir.
Ancak bu kısıtlama, JavaScript'in modern web'in devasa asenkron yüklerini taşımasına engel değildir.
Modern uygulamaların talep ettiği uzun süreli işlemler; ağ istekleri, zamanlayıcılar veya DOM olayları, JavaScript'in ana iş parçacığını asla kilitlemez.
Bu mucizevi denge, dilin kendi sentaksından ziyade, onu çevreleyen Yürütme Ortamının sağladığı mimari bileşenler sayesinde kurulur.
Runtime Gücü: Tarayıcı ve Node.js KatmanlarıJavaScript motoru yalnız değildir ve tarayıcı veya Node.js ortamı, motora asenkron yetenekler kazandıran bir dizi
"yardımcı oyuncu" sunar.
Bu mekanizmanın kalbi olan Event Loop, Call Stack ile Callback Queue arasındaki trafiği yöneten görünmez bir orkestra şefi gibidir.
Bir asenkron görev başlatıldığında, JavaScript motoru bu görevi hemen Web APIs katmanına delege eder.
Motor, görevin bitmesini beklemeden sıradaki işine geçerken; yardımcı katmanlar işi arka planda tamamlar.
Bu mimari, JavaScript'in tek şeritli bir yol olmasına rağmen, yan yollar ve viyadükler sayesinde trafik sıkışıklığı yaşamamasını sağlar.
Mimari Bileşenlerin Rol DağılımıBu karmaşık iş birliğini anlamak için sistemin dört ana sütununu tanımak zorunludur:
- Call Stack: Mevcut yürütülen kodların istiflendiği "şimdi" alanı.
- Web APIs: Zamanlayıcılar ve ağ istekleri gibi ağır işlerin yapıldığı "arka bahçe".
- Callback/Task Queue: Tamamlanan işlerin "hazır" beklediği bekleme salonu.
- Event Loop: Bekleme salonundakileri, stack boşaldığı anda içeri alan "güvenlik görevlisi".
Call Stack (Çağrı Yığını): Senkron Yürütmenin Kalbi LIFO Disiplini ve Yürütme Hattı Yönetimi
Call Stack, bir JavaScript motorunun en temel veri yapısıdır.
Kodun yürütülme sırasını anlık olarak takip eden bu düzenek, ister senkron ister asenkron olsun, her bir kod satırının "nihai durak" noktasıdır.
Hiçbir JavaScript kodu bu yığından geçmeden işlemci tarafından yürütülemez.
LIFO Prensibi: Son Giren, İlk ÇıkarCall Stack, LIFO prensibiyle çalışır.
Tıpkı üst üste dizilmiş bir tabak yığını gibi, yürütülmek üzere en son eklenen fonksiyon, işi bittiğinde yığından çıkarılan ilk elemandır.
Bir fonksiyon çağrıldığında, onun yürütme çerçevesi yığına eklenir ( push ).
Fonksiyonun içindeki işlemler tamamlanıp return gerçekleştiğinde ise çerçeve yığından atılır ( pop ).
Tek İş Parçacığı ve Blocking (Engelleme) RiskiJavaScript'in tek iş parçacıklı doğası gereği, Call Stack aynı anda yalnızca bir adet yürütme çerçevesi tutabilir.
Eğer yığına eklenen bir fonksiyon devasa bir hesaplama veya sonsuz bir döngü içeriyorsa, bu durum Blocking yaratır.
Yığın bu ağır işle meşgulken, tarayıcı ne kullanıcı tıklamalarına cevap verebilir ne de ekranı güncelleyebilir; bu da kullanıcı deneyiminin felç olması anlamına gelir.
Call Stack'in durumu, asenkron mimarideki en kritik trafik ışığıdır. Event Loop'un birincil görevi bu yığını sürekli dikizlemektir.
Call Stack tamamen boşalmadıkça, Event Loop hiçbir asenkron görevi kuyruktan alıp buraya taşımaz.
Bu katı kural, JavaScript'in çoklu görevleri yönetirken bile veri tutarlılığını ve deterministik yapısını korumasını sağlar.
Web APIs (Tarayıcı/Ortam İşlevleri) Asenkron Kapı ve Arka Plan Operasyon Merkezi
Web APIs veya C++ API'leri, JavaScript'in asenkron mimarisindeki çoklu görev yeteneğinin gizli kahramanlarıdır.
Bu bileşenler, sanılanın aksine JavaScript motorunun içinde değil, onu çevreleyen Runtime içinde yer alır.
JavaScript motoru "yürütme" ile ilgilenirken, Web APIs "bekleme ve izleme" operasyonlarını üstlenir.
Rolü: İzolasyon ve Çoklu Görev Sağlamaİzolasyon Felsefesi: Web APIs'in temel rolü, Call Stack'te kalsa sistemi kilitleyecek olan uzun süreli görevleri ana iş parçacığından izole etmektir.
Çoklu Görev Sağlama: Web APIs, alt seviyede C++ gibi çok iş parçacıklı (multi-threaded) dillerle inşa edilmiştir.
Bu sayede, aynı anda on dökümanı indirebilir, yirmi farklı zamanlayıcıyı takip edebilir ve yüzlerce DOM olayını dinleyebilir.
Tüm bu "paralel" gibi görünen süreçler, JavaScript'in o meşhur tek şeritli yolunu hiç meşgul etmeden arka planda yürütülür.
İşleyiş: Görev Devretme ve RaporlamaMekanizmanın çalışma prensibi kusursuz bir "delege etme" sanatıdır:
-
Görev Devri: Motor,
setTimeoutveyafetchgibi bir komutla karşılaştığında, Call Stack bu isteği milisaniyeler içinde işleyip Web APIs katmanına fırlatır ve hemen bir sonraki satıra geçer. - Arka Plan Takibi: Web APIs, kendisine devredilen görevi motorun dışında, tamamen bağımsız olarak izler. Örneğin, 3 saniyelik bir sayaç çalışırken motor kendi işine bakar.
- Sonuç Raporlama: İşlem bittiğinde (veri geldiğinde veya zaman dolduğunda), Web APIs sonucu doğrudan Call Stack'e sokamaz. Bunun yerine, ilgili geri çağrı fonksiyonunu (callback), Call Stack'e girmek üzere Task Queue (Görev Kuyruğu) bölümüne yerleştirir.
Sonuç olarak, Web APIs, JavaScript'in kısıtlı doğasını genişleten bir özgürlük alanıdır.
Bu katman olmasaydı, her ağ isteğinde tarayıcımızın donduğu ilkel bir web deneyimine hapsolurduk.
Callback Kuyrukları: Önceliklendirme ve Bekleme Odaları Görevlerin Hiyerarşik Sıralanması ve Kuyruk Yönetimi
Web APIs katmanına devredilen asenkron operasyonlar tamamlandığında, bu işlemlerin sonuçlarını taşıyan geri çağrı fonksiyonları doğrudan Call Stack'e sızamazlar.
JavaScript'in asenkron mimarisi, bu aşamada görevlerin önem derecesine göre sınıflandırıldığı iki farklı Kuyruk mekanizması kullanır.
Bu yapı, sistemin hangi işe ne zaman odaklanacağını belirleyen bir trafik kontrol merkezidir.
1. Microtask Queue (Yüksek Öncelikli Hat)Bu kuyruk, modern JavaScript'in asenkron kalbi olan Promise tabanlı yapıların "V.I.P." geçiş hattıdır.
Kuyruklar arasındaki hiyerarşide en üstte yer alır ve mutlak önceliğe sahiptir.
- İçerik: .then(), .catch(), .finally() blokları ve async/await yapılarının devam kodları burada bekler.
- Öncelik Felsefesi: Promise zincirleri, uygulama mantığının atomik parçaları kabul edilir. Bir sonraki kullanıcı tıklamasından veya zamanlayıcıdan önce, mevcut veri işleminin tamamlanması sistem tutarlılığı için kritiktir.
"Callback Queue" olarak da bilinen bu kuyruk, nispeten daha ağır ve bağımsız asenkron görevlerin toplandığı ana bekleme alanıdır.
- İçerik: setTimeout, setInterval, I/O işlemleri, kullanıcı olayları (click, scroll) ve UI Rendering (ekran çizimi) olaylarını barındırır.
- FIFO Prensibi: Bu kuyrukta "ilk giren ilk çıkar" kuralı esastır. Görevler kronolojik sıraya göre dizilir.
Event Loop'un çalışma algoritmasındaki en katı kural şudur: Call Stack boşaldığında, Microtask Queue içinde tek bir görev bile kalmayana kadar tüm kuyruk temizlenir.
Ancak Microtask'lar bittikten sonra Macrotask Queue'dan tek bir görev alınır.
Bu döngü, asenkron işlemlerin kaotik görünmesine rağmen aslında ne kadar disiplinli bir hiyerarşiyle yönetildiğinin kanıtıdır.
Özet olarak, Callback Kuyrukları, JavaScript'in zamanı parçalara bölme yeteneğidir.
Bu yapı sayesinde, ağır bir ağ isteğinin sonucu, basit bir zamanlayıcıdan daha sonra tamamlansa bile, sistemdeki öncelik dengesi sayesinde her zaman doğru ve tutarlı sırada yürütülür.
Event Loop (Olay Döngüsü) Orkestra Şefi: Asenkron Akışın Görünmez Koordinatörü
Event Loop, JavaScript'in asenkron ekosistemindeki tüm parçaları birbirine bağlayan ve yürütme motorunun dışındaki dünyayı koordine eden, sonsuz bir döngü mekanizmasıdır.
JavaScript'in "tek şeritli bir yol" olmasına rağmen, binlerce eşzamanlı görevi yönetebilmesini sağlayan mimari deha tam olarak burada yatar.
Görevi: Sürekli Denetim ve Karar MekanizmasıEvent Loop, adeta bir Orkestra Şefi titizliğiyle çalışır ve milisaniyelik periyotlarla şu iki kritik durumu çapraz kontrole tabi tutar:
- Ana Yürütme Kontrolü: Call Stack'in tamamen boş olup olmadığını izler. Eğer stack doluysa, motor hala senkron bir iş yürütüyordur ve Event Loop sessizce sırasını bekler.
- Geri Çağrı Hazırlığı: Callback kuyruklarında ( Microtask ve Macrotask ) işlenmeyi bekleyen, "arka bahçeden" dönmüş hazır görevler olup olmadığını denetler.
Call Stack boşaldığı an, Event Loop altın kuralını devreye sokar ve trafiği şu hiyerarşik sırayla yönetir:
1. Microtask'ların Mutlak Dominansı: Event Loop önce Microtask Queue'ya dalar.
Eğer burada bir Promise çözümü varsa, kuyruk tamamen boşalana kadar tüm Microtask'ları Call Stack'e iter.
Bu aşama bitmeden tarayıcı ne ekranı çizer ne de diğer görevlere geçer.
2. Macrotask Geçişi: Microtask hattı tamamen temizlendikten sonra, Event Loop Macrotask Queue'dan yalnızca tek bir görevi alır ve Call Stack'e gönderir.
Döngüsel Devamlılık: Kesintisiz YaşamStack'e gönderilen o tek Macrotask biter bitmez, Event Loop tekrar en başa döner: Önce Stack'i, sonra Microtask'ları kontrol eder.
Bu sonsuz döngü, JavaScript uygulamalarının donmadan, akıcı ve her zaman tepkisel kalmasını sağlayan temel yaşam enerjisidir.
Sonuç olarak, Event Loop, asenkron karmaşayı bir düzene sokan en büyük dengeleyicidir.
Bu döngü sayesinde, bir taraftan ağır veriler işlenirken, diğer taraftan kullanıcı etkileşimleri ve zamanlayıcılar tutarlı bir ritimle hayat bulur.
const istek = new Promise((resolve, reject) => {
const basarili = true;
basarili ? resolve("OK") : reject("Hata");
});
Yeni bir Promise, resolve/reject ile tek sonuç üretir.
A new Promise resolves or rejects once via resolve /
reject.
await Promise.all([istekA, istekB, istekC]);
Tüm Promiselar başarılı olduğunda sonuç döner; ilk hata zinciri
kırar.
Returns when every Promise succeeds; the first rejection breaks
the
chain.
istek
.then(sonuc => isleyici(sonuc))
.then(cikti => kaydet(cikti))
.catch(hata => console.error(hata));
Her .then bir değer döndürür; .catch zincirdeki tüm hataları
yakalar.
Each .then returns a value; .catch collects errors across the
chain.
istek.finally(() => temizleSpinner());
Başarı ya da hata fark etmeksizin çalışır; temizlik için
idealdir.
Runs regardless of success or failure; ideal for cleanup.
async function yukle() {
try {
const veri = await istek();
return veri;
} catch (hata) {
throw hata;
}
}
await Promise çözümlerini duraklatır; try/catch senkron hata akışı
sağlar.
await pauses for Promise results; try/catch mirrors synchronous
error
flow.
const [profil, bildirimler] = await Promise.all([
fetchProfil(),
fetchBildirim()
]);
Bağımsız istekler Promise.all ile paralel beklenir.
Use Promise.all to await independent requests in parallel.
const response = await fetch(url);
if (!response.ok) throw new Error(response.status);
const data = await response.json();
response.ok kontrolü HTTP hatalarını yakalar; ikinci await body'i
JSON'a
çevirir.
Check response.ok for HTTP errors; the second await turns the body
into
JSON.
const controller = new AbortController();
const { signal } = controller;
await fetch(url, { signal });
controller.abort();
AbortController uzun istekleri iptal eder; timeout ve kullanıcı
iptalleri
için idealdir.
AbortController cancels long requests; perfect for timeouts or
user
aborts.
for (let deneme = 0; deneme < maks; deneme++) {
try { return await istek(); }
catch (hata) { await bekle(2 ** deneme * baz); }
}
Üstel geri çekilme (exponential backoff) geçici hataları
sakinleştirir.
Exponential backoff mitigates transient failures
gracefully.
if (breaker.acik()) return breaker.fallback();
const sonuc = await istek();
Devre kesici yoğun hata dönemlerinde sistemi korur ve fallback
döndürür.
Circuit breaker protects the system during heavy failure periods
and yields
fallbacks.
Öğrenme Yolu
JavaScript öğrenme yolculuğunuzda neredesiniz?
Bu bölüm, JavaScript öğrenme yolculuğunuzdaki ilerlemenizi görselleştirir. Aşağıda göreceğiniz adımlar, konular arasındaki mantıksal sıralamayı ve öğrenme akışını temsil eder. Tamamlanan konular mavi tonlarda gösterilir ve üzerinde bir onay işareti bulunur. Aktif konu, şu anda üzerinde çalıştığınız bölümdür ve parlak mavi renkle vurgulanır. Sonraki adımlar ise henüz tamamlanmamış konuları gösterir ve daha soluk tonlarda görüntülenir.
Her adım arasındaki oklar, öğrenme sırasını ve konular arasındaki bağlantıyı gösterir. Bu yapı, hangi konuları tamamladığınızı, hangi konuda olduğunuzu ve sıradaki adımlarınızı net bir şekilde görmenizi sağlar.
Modülerlik ve Kod Organizasyonu
ES Modülleri, Bağımlılık Enjeksiyonu ve IoC Konteynerleri
Asenkron Programlama
Promise, async/await ve JSON işlemleri