Berat Bozkurt

Berat Bozkurt




Benzer Yazılar

Micro Frontend Mimarisi (1. Bölüm)
19 Nisan 2025

Micro Frontend Mimarisi (1. Bölüm)

Javascript’te Immutable ve Mutable Konusu
23 Ekim 2024

Javascript’te Immutable ve Mutable Konusu

Frontend’de Hata Nasıl Çözülür? 101
21 Ekim 2024

Frontend’de Hata Nasıl Çözülür? 101

Javascript'in Gizli Kahramanı: Event Loop ve Promise'ler

20 Mart 2025 • 42 görüntülenme •
Javascript'in Gizli Kahramanı: Event Loop ve Promise'ler
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.
  1. Event Loop nedir? Call Stack, Microtask Queue, Task Queue.
  2. Promise'lar ve Event Loop'ta yerleri.
  3. Örnek kodlar.

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;
  1. Call Stack tüm işlerini bitirdi mi? Boş mu? Evet. (Anında bu işleri yap.)
  2. Microtask Queue'daki tüm işleri çalıştır. Bittikten sonra bir sonraki adıma geç. (Benim önceliğim var.)
  3. 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.

Örnek Kodlar

  • setTimeout
console.log("Başla");
setTimeout(() => console.log("Timeout"), 0);
console.log("Bitti");

// Başla
// Bitti
// Timeout
  • Promise
console.log("Başla");

Promise.resolve().then(() => console.log("Promise"));

console.log("Bitti");

// Başla
// Bitti
// Promise
  • Zincirleme Promise
console.log("Başla");

Promise.resolve()
  .then(() => {
    console.log("Promise 1");
    return Promise.resolve();
  })
  .then(() => console.log("Promise 2"));

console.log("Bitti");

// Başla
// Bitti
// Promise 1
// Promise 2
  • Promise ve setTimeout
console.log("1. Senkron adım");

setTimeout(() => console.log("4. Task Queue’dan geldim"), 0);

Promise.resolve()
  .then(() => console.log("2. Microtask: Promise 1"))
  .then(() => console.log("3. Microtask: Promise 2"));

console.log("1.5 Senkron adım");

// 1. Senkron adım
// 1.5 Senkron adım
// 2. Microtask: Promise 1
// 3. Microtask: Promise 2
// 4. Task Queue’dan geldim
  • Gerçek bir örnek
console.log("Sayfa yükleniyor");

setTimeout(() => console.log("Reklamlar yüklendi"), 0);

fetch("https://jsonplaceholder.typicode.com/todos/1")
  .then((response) => response.json())
  .then((data) => console.log("Görev:", data.title));

console.log("Kullanıcı bekliyor");

// Sayfa yükleniyor
// Kullanıcı bekliyor
// Görev: delectus aut autem
// Reklamlar yüklendi

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.
Esenlikler...
•
X (Twitter)'da paylaş