Javascript'in Gizli Kahramanı: Event Loop ve Promise'ler
20 Mart 2025 • 31 görüntülenme •
Selamlar, bu aralar aktif olarak mülakatta sorulan sorular ile biraz daha Javascript'i derinlemesine öğrenmeye ve anlamaya çalışıyorum. Bu zamana kadar neredeyse çoğu şeyi pratikte öğrenerek uyguladım ve o şekilde yapmaya da devam ediyorum.
Frontend dünyasını 5 yılı devirdikten sonra biraz daha prensibleri ve mantığını öğrenmeyi kendime bir hedef koydum. Bunu aslında mülakatta sorulan basit gözükse de aslında saatler süren bir araştırma konusu. Çünkü konu konuyu açıp bir soru üzerinden beklemediğim kadar fazla teknik konuları öğrenebiliyorum. Bu da aslında javascript tarafında kendimi geliştirmeye hatta ve hatta sadece javascript kalmayıp genel prensibleri de öğrenme imkanım oluyor.
Bu yazıya benzer bir çok yazı görmüş olabilirsiniz. Ama eminim ki daha önce görmediğiniz bir konuyu anlatmaya çalışacağım. Buyrun hangi başlıkları ve başlık altında hangi anahtar kelimeleri inceleyeceğiz, bakalım.
Promise'lar neden setTimeout'tan önce çözülüyor hiç düşündünüz mü? Burada devreye Event Loop giriyor. Hazırsanız başlayalım.
Event Loop Nedir?
Javascript single thread (tek iş parçacığı) ve senkron olarak çalışır. Event Loop, Javascript'in asenkron işlemleri yönetmesini sağlayan bir mekanizmadır. setTimeout, Promise'lar veya bir butona tıkladığımızda yaptığımız asenkron olayların sırayla ve düzgün çalışmasında Event Loop devreye giriyor.
Javascript'te hangi kod parçasının ne zaman çalıştıracağına karar verir. Bunları şu parçalarla yapar:
Call Stack
O an çalışacak olan kod ne ise burada yer alır. Burada konsol çıktıları, değişkenler, fonksiyonlar, döngüler, matematiksel işlemler vs. vardır. Bunlar olduğu gibi işlenecek ve çalışacaktır. Daha sonra Call Stack boşalır ve daha sonra asenkron işlere bakılır. Hangi sıralamada bakıldığında biraz sonra inceleyeceğiz.
Task Queue
Asenkron işlerin sıraya girdiği yer burasıdır. Genelde tarayıcı veye Node.js tarafından tetiklenen işler burada olur. setTimeout, setInterval, event handlers, DOM eventleri vs. vardır.
Microtask Queue
Daha yüksek asenkron işleri içerir. Genelde Promise'lerle ilişkilidir. Burada Promise'lar, queueMicrotask, MutationObserver vs. vardır.
Buradaki takip sırası görselde de anlaşılacağı gibi şöyle ilerler;
Call Stack tüm işlerini bitirdi mi? Boş mu? Evet.(Anında bu işleri yap.)
Microtask Queue'daki tüm işleri çalıştır. Bittikten sonra bir sonraki adıma geç. (Benim önceliğim var.)
Task Queue'daki işleri de hallet. (Benim acelem yok, yaparsın bi ara.)
Promise'lar ve Event Loop'ta Yerleri
Javascript'ta asenkron işlerin çoğu Promise'lar ile yapılır. Bir API çağrısında veri geldiğinde nasıl hemen DOM'u günceleyebiliyoruz? Ya da bir Promise neden setTimeout'tan önce çalışır? Bu gibi sorular aklımızda varsa bunların cevabını birlikte öğreneceğiz.
Promise'da üç durum söz konusudur:
Pending (Bekleme): İşlemin henüz bitmeme durumu.
Resolved (Çözüldü): İşlemin başarılı olma durumu.
Rejected (Reddedildi): İşlemin başarısız olma durumu.
Promise'lar, .then, .catch veya .finally gibi metodlarla bu sonuçları işler. Ama buradaki asıl konu, bu metodaların Event Loop'ta nasıl sıraya girdiğidir.
Promise'lar, Microtask Queue'ya aittir. Yani Promise çözüldüğünde veya reddedildiğinde onun .then, .catch veya .finally blokları hemen Microtask Queue'ya eklenir. Call Stack boşaldığında, önce Microtask Queue çalışacağından dolayı diğer asenkron işlerden önce çalıştığına bir cevaptır.
Promise'lar, Microtask Queue'da olmasıyla birlikte bunların hızlı ve güvenilir olduğunu rahatlıkla söyleyebiliriz. Böylelikle istenilen verileri daha önce alır ve kullanıcıya hızlı bir deneyim sunabiliriz.
Javascript'te asenkron tarafı ilk başlarda kafa karıştırıcı gibi gözüküyor olabilir ama inanın zaman geçtikçe ve pratik yaptıkça her şey daha fazla anlam kazanıyor. Böylelikle kolay bir şekilde kullanabiliyor ve anlamış oluyorsunuz. Şimdi bunları öğrenince "Vayy be!" dedim ve bir sonraki kullanımlarımda bu aklıma gelecek ve daha bilinçli bir şekilde kullanmış olacağım.