Cansu Arı Logo
Blog
Nedir?

JavaScript’te Microtask vs Macrotask: Event Loop’u Gerçekten Anlamak

Event Loop sadece teori değil! Promise’ler, setTimeout’lar ve task kuyrukları arasındaki farkı canlı örneklerle çözüyoruz.

  • #JavaScript

Skip to content

Event Loop’un Perde Arkası: Microtask vs Macrotask

JavaScript tek iş parçacıklı (single-threaded) bir dil olabilir, ama bu onun tek seferde sadece bir şey yapabildiği anlamına gelmez. Asıl sihir, Event Loop’ta gizlidir.

Event Loop'u, JavaScript motorunun kalp atışı gibi düşün. Kodlar sırayla değil, akıllıca organize edilmiş bir kuyruğa göre çalışır. Promise’ler, setTimeout’lar, hatta DOM güncellemeleri bile bu döngüde sıraya girer. Yani her “bekle!” dediğinde (örneğin bir fetch isteği ya da animasyon), bu kalp bir döngü daha atar.

Basit Bir Örnekle Başlayalım

console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
console.log('4');
Çıktı sırasıyla “1, 2, 3, 4” gelir, dimi?

Nope. Gerçek çıktı: 1, 4, 3, 2

Neden Böyle Oldu?

Çünkü JavaScript’te iki tür görev (task) kuyruğu vardır:

  1. Microtask Queue → Promise’ler, queueMicrotask gibi mini görevler buraya gider.
  2. Macrotask QueuesetTimeout, setInterval, requestAnimationFrame gibi işler burada sıradadır.
Event Loop her turda şunu yapar:
  1. Call stack boş mu? Eğer evet → sıradaki microtask’leri çalıştır.
  2. Tüm microtask’ler bittikten sonra → ekranı render et.
  3. Ardından bir sonraki macrotask’e geç.
Bu yüzden Promise (microtask) içindeki kod, setTimeout (macrotask) içindekinden önce çalışır.

Event Loop Aşamaları Adım Adım

Event Loop’u kalp döngüsü gibi düşünelim:

  1. Call Stack (çağrı yığını): Senkron kodlar burada çalışır.
  2. Microtask Queue: Hızlı, küçük işler (Promise’ler, async/await sonuçları).
  3. Render Aşaması: Tarayıcı ekrana yeni görünümü çizer.
  4. Macrotask Queue: Daha uzun, planlı işler (setTimeout, network yanıtları, I/O).
Bu döngü saniyede onlarca, hatta yüzlerce kez gerçekleşir. İşte JavaScript’in “tek iş parçacıklı ama birden fazla işi aynı anda yapıyor gibi görünmesinin” sırrı burada.

Microtask Nedir?

Microtask’ler minik ama kritik görevlerdir. Genellikle Promise’lerin çözülmesi, DOM güncellemeleri sonrası mikro hesaplamalar ya da queueMicrotask() ile planlanan küçük işler bu kategoriye girer.

queueMicrotask(() => {
console.log('Bu, event loop bitiminde çalışır.');
});

Bir loop turu biter bitmez, render’dan hemen önce çalışırlar. Yani küçük ama hızlı görevler için mükemmeldirler.

Ama dikkat! Sonsuz microtask zincirleri (Promise.then().then().then()...) oluşturursan render işlemi gecikir, çünkü tarayıcı çizim yapmadan sürekli microtask çalıştırmakla meşgul olur. 🐢

Macrotask Nedir?

Macrotask’ler, bir sonraki döngüde yapılacak işlerdir. Tarayıcı animasyonları, kullanıcı etkileşimleri, ağ yanıtları hep buraya girer.

setTimeout(() => console.log('Macrotask!'), 0);

0 milisaniye bile versen, bu kod bir sonraki event loop turunda çalışır. Çünkü önce microtask kuyruğunun boşalması beklenir. Yani 0 demek “şimdi hemen” değil, “birazdan, sıran gelince” demektir. 😊

Karşılaştırma Tablosu

ÖzellikMicrotaskMacrotask
ÖrneklerPromise, queueMicrotasksetTimeout, setInterval, requestAnimationFrame
ZamanlamaAynı event loop turunda, render öncesiSonraki event loop turunda
Kullanım AlanıKüçük ve acil işlemlerDaha büyük veya gecikmeli işler
Performans EtkisiDüşükOrta (render gecikebilir)
Sıradaki ÖncelikDaha yüksekDaha düşük

Node.js Dünyasında

Node tarafında işler biraz farklı görünür ama mantık aynıdır. process.nextTick() microtask gibi, setImmediate() ise macrotask gibidir.

setTimeout(() => console.log('timeout'), 0);
setImmediate(() => console.log('immediate'));
process.nextTick(() => console.log('nextTick'));

Çıktı genellikle: nextTick → timeout → immediate olur. Node.js bile aynı prensibi takip eder, sadece kendi kuyruğu biraz farklı isimlendirilmiştir.

Gerçek Hayattan Bir Analoji

Event Loop’u bir konser sahnesi gibi düşün.

  • Microtask’ler: Sahne arkasında ışık ve ses ayarını yapan ekip -- her performans sonrası hızla girip küçük düzeltmeler yaparlar.
  • Macrotask’ler: Bir sonraki sanatçı -- sahneye çıkmadan önce sırada bekler.
  • Render: Seyircinin gerçekten gördüğü sahne.

İşte bu yüzden Promise’ler (microtask) her zaman setTimeout’lardan (macrotask) bir adım önde çalar.

Performans ve Tuzaklar

  • Çok fazla microtask, render gecikmesine neden olabilir. Tarayıcı hiçbir zaman “şimdi ekrana çizim yapayım” diyemez.
  • Aşırı setTimeout kullanımı ise CPU’yu yorar ve frame drop yaşanır.
  • Promise zincirleri oluştururken araya küçük gecikmeler (setTimeout) eklemek bazen performansı dengeleyebilir.

Sonuç

Event Loop JavaScript’in görünmeyen kahramanıdır. Onu anlamak, async davranışları tahmin edebilmeni sağlar. Promise ve setTimeout arasındaki fark küçük görünse de, UI hissinde dev bir fark yaratır.

Microtask’leri hızlı işlemler için, macrotask’leri zaman planlaması gerektiren işler için kullan.

All tags
  • JavaScript