Event Loop — JavaScript

Coba bayangin warung mie ayam yang cuma ada SATU tukang masak. Kalo tiap pesanan harus selesai dulu sebelum tukang kerjain pesanan berikutnya — kamu antri 30 me

Coba bayangin warung mie ayam yang cuma ada SATU tukang masak. Kalo tiap pesanan harus selesai dulu sebelum tukang kerjain pesanan berikutnya — kamu antri 30 menit cuma buat dapet mie. Tapi kenyataannya warung jalan lancar walau cuma satu tukang. Kenapa? Karena tukangnya pinter — dia kerjain bagian yang bisa langsung (bumbu, racik), terus pas mie lagi rebus dia gak nungguin (5 menit), dia ambil pesanan baru, balik lagi pas mie udah mateng. Itu Event Loop di JavaScript: walaupun single-threaded, dia bisa "multitask" lewat sistem antrian + prioritas yang cerdik.

💡 Aturan urutan eksekusi. (1) Sync code di Call Stack dulu. (2) Habis stack kosong, jalanin SEMUA microtask (Promise). (3) Baru pop SATU macrotask (setTimeout, click event). Ulang. Pola ini yang bikin Promise selalu nyalip setTimeout — pengetahuan kunci buat debug timing async.

Event Loop adalah mekanisme yang mengatur eksekusi kode:

  1. Call Stack — tempat kode dijalankan (satu per satu)
  2. Web APIs — browser menangani async (setTimeout, fetch, event listener)
  3. Callback Queue — antrian callback yang siap dijalankan
  4. Microtask Queue — antrian Promise (prioritas lebih tinggi)
<title id="eventloop-t">Event loop: call stack, web APIs, microtask queue di atas callback queue.</title>Call Stackmain()log("4")LIFO — atas dieksekusiWeb APIssetTimeoutfetch, DOM eventsMicrotask QPromise.thenqueueMicrotaskCallback QsetTimeout cbsetInterval cbUrutan: stack kosong → semua microtask → satu macrotask → ulangMicrotask selalu menang sebelum macrotask berikutnya jalan.Promise.then chain bisa "kelaparan-kan" setTimeout(0).
Event loop pop microtask SEMUA dulu, baru pop satu macrotask. Itu sebabnya Promise menang.
console.log("1");           // → Call Stack
setTimeout(() => {
  console.log("2");         // → Callback Queue (setelah 0ms)
}, 0);
Promise.resolve().then(() => {
  console.log("3");         // → Microtask Queue
});
console.log("4");           // → Call Stack

// Output: 1, 4, 3, 2

Urutan eksekusi:

  1. Synchronous code di Call Stack dulu
  2. Microtasks (Promise) dijalankan
  3. Macrotasks (setTimeout, setInterval) terakhir

🎭 Analogi sehari-hari

Event loop = kasir di warung Mbak Lia:

Karena JavaScript single-thread (cuma satu kasir), kalau ada pelanggan yang lama (loop berat), antrean lain stuck = halaman freeze.

⚠️ Jebakan yang sering ditemui:

  • setTimeout(fn, 0) tidak benar-benar 0ms — minimal ~4ms di browser, dan harus tunggu microtask queue kosong dulu. Untuk async paling cepat, pakai queueMicrotask(fn) atau Promise.resolve().then(fn).
  • Promise chain bisa block macrotask.then() yang resolve-nya cepat dan terus chain, microtask queue tidak pernah kosong → setTimeout tidak pernah dapat giliran.
  • Long-running sync code blokir UI — JavaScript single-threaded, for (let i = 0; i < 1e9; i++) bikin halaman freeze. Pecah dengan setTimeout atau Web Workers.
  • async function tetap masuk microtaskawait setara dengan .then(), jadi kode setelah await masuk microtask queue, bukan langsung lanjut.
  • Event handler tidak bersarang — kalau di dalam click handler ada await, handler kedua bisa fire sebelum yang pertama selesai. Pakai flag/AbortController.

TL;DR: Event Loop bikin JavaScript single-threaded bisa "multitask". Urutan eksekusi: (1) sync code di Call Stack, (2) habis stack kosong jalanin SEMUA microtask (Promise), (3) baru pop SATU macrotask (setTimeout/event). Ulang. Microtask selalu menang sebelum macrotask berikutnya — pengetahuan kunci debug timing async. Long-running sync code = freeze halaman (single-thread limit).

Yang akan kamu pelajari