Event Loop JavaScript: Rahasia di Balik "Sihir" Asynchronous yang Sering Disalahpahami

⏱ - menit baca

diagram Call Stack, Web APIs, Microtask Queue, Callback Queue, dan Event Loop yang saling terhubung

JavaScript itu single-threaded — hanya bisa mengerjakan satu hal dalam satu waktu. Tapi bagaimana mungkin ia bisa menangani fetch(), setTimeout(), dan event klik pengguna secara bersamaan tanpa membuat browser membeku? Jawabannya ada pada satu mekanisme yang sering disebut tapi jarang benar-benar dipahami: Event Loop.

Call Stack: Tempat Kode Benar-benar Dieksekusi

Bayangkan Call Stack seperti tumpukan piring. Setiap kali sebuah fungsi dipanggil, ia "ditumpuk" di atas. Ketika fungsi selesai dijalankan, ia diangkat dari tumpukan. JavaScript hanya bisa mengeksekusi fungsi yang berada di paling atas tumpukan ini — satu per satu, tidak ada yang paralel.

function main() {
  console.log("Mulai");
  fetchData();
  console.log("Selesai");
}
main();

Ketiga baris di atas masuk dan keluar dari Call Stack secara berurutan. Sejauh ini, semuanya masih synchronous — tidak ada yang istimewa.

Web APIs: Tempat "Titip" Pekerjaan Asynchronous

Masalah muncul ketika ada operasi yang butuh waktu, seperti setTimeout() atau fetch(). JavaScript tidak menunggu operasi ini selesai di Call Stack — sebaliknya, ia "menitipkan" pekerjaan tersebut ke Web APIs yang disediakan browser (bukan bagian dari JavaScript engine itu sendiri, melainkan environment tempat JavaScript berjalan).

Begitu dititipkan, Call Stack langsung bebas melanjutkan baris kode berikutnya — inilah yang membuat JavaScript terasa "tidak menunggu".

Dua Jenis Antrean: Microtask vs Macrotask (Callback Queue)

Setelah Web API menyelesaikan tugasnya, hasilnya tidak langsung masuk ke Call Stack begitu saja. Ia harus antre dulu, dan ternyata ada dua jenis antrean dengan prioritas berbeda:

  • Microtask Queue — tempat antrean untuk Promise.then(), catch(), finally(), dan queueMicrotask(). Antrean ini punya prioritas lebih tinggi.
  • Callback Queue (Macrotask Queue) — tempat antrean untuk setTimeout(), setInterval(), dan event handler seperti klik atau scroll.

Event Loop: Sang Pengatur Lalu Lintas

Inilah inti dari semuanya. Event Loop terus-menerus memeriksa satu hal sederhana: apakah Call Stack sedang kosong? Jika ya, ia akan mengambil tugas dari antrean dan memasukkannya ke Call Stack untuk dieksekusi.

Aturannya cukup ketat: seluruh isi Microtask Queue harus habis terlebih dahulu sebelum Event Loop mengambil satu tugas dari Callback Queue. Ini menjelaskan kenapa kode berikut kadang membingungkan bagi pemula:

console.log("1");

setTimeout(() => console.log("2"), 0);

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

console.log("4");

Meski setTimeout diberi delay 0 milidetik, urutan output yang muncul adalah 1, 4, 3, 2 — bukan 1, 2, 3, 4. Alasannya, console.log("1") dan console.log("4") dieksekusi langsung secara synchronous di Call Stack. Sementara itu, Promise (microtask) selalu mendapat giliran lebih dulu dibanding setTimeout (macrotask), meski keduanya sama-sama "menunggu" Call Stack kosong.

Kenapa Ini Penting Dipahami?

Memahami Event Loop bukan sekadar teori akademis. Ini membantu menjawab pertanyaan-pertanyaan praktis yang sering muncul saat debugging:

  • Kenapa console.log di dalam .then() kadang muncul lebih dulu dari yang diperkirakan?
  • Kenapa fungsi yang "berat" (heavy computation) bisa membuat seluruh halaman web terasa macet, padahal tidak ada error?
  • Kenapa async/await sebenarnya hanyalah "gula sintaksis" di atas Promise, dan tetap tunduk pada aturan microtask yang sama?

Kesalahpahaman Umum yang Perlu Diluruskan

Banyak developer pemula mengira JavaScript itu multi-threaded karena bisa menangani banyak hal "sekaligus". Padahal, yang sebenarnya terjadi adalah satu thread utama yang dibantu oleh Web APIs di luar JavaScript engine untuk menangani operasi yang memakan waktu, lalu hasilnya diantrekan kembali untuk dieksekusi satu per satu di Call Stack yang sama.


Pada akhirnya, Event Loop adalah jantung dari sifat asynchronous JavaScript yang membuatnya begitu powerful untuk aplikasi web modern. Memahaminya secara mendalam bukan hanya soal lulus wawancara teknis — ini adalah fondasi untuk menulis kode yang predictable, menghindari bug yang sulit dilacak, dan benar-benar memahami apa yang terjadi "di balik layar" setiap kali kita menulis setTimeout atau .then().


Ditulis oleh

Inats Studio

💬 Komentar ()

Punya pertanyaan atau tanggapan? Yuk diskusi di kolom komentar.

✍ Tulis Komentar