Pernahkah Anda bertanya-tanya bagaimana JavaScript, sebuah bahasa pemrograman single-threaded, dapat menangani banyak tugas secara bersamaan tanpa membuat aplikasi Anda “macet”? Jawabannya terletak pada mekanisme asynchronous JavaScript dan inti dari semuanya: Event Loop. Memahami cara kerja Event Loop adalah kunci untuk membangun aplikasi web yang responsif dan efisien.
Artikel ini akan menguak misteri di balik Event Loop JavaScript. Kita akan menjelajahi bagaimana mekanisme ini mengatur eksekusi kode, bagaimana ia berinteraksi dengan Call Stack, Web APIs, dan Callback Queue. Dengan pemahaman yang lebih dalam tentang konsep-konsep ini, Anda akan dapat menulis kode JavaScript yang lebih efisien dan teroptimasi. Mari kita mulai!
Daftar Isi
Apa Itu Event Loop dalam JavaScript?
Dalam dunia JavaScript yang dinamis, pemahaman mendalam tentang event loop menjadi kunci untuk menguasai mekanisme asynchronous. Sederhananya, event loop adalah model eksekusi kode yang memungkinkan JavaScript untuk menangani tugas-tugas yang memakan waktu, seperti operasi I/O, tanpa memblokir alur utama program.
Bayangkan event loop sebagai seorang pelayan restoran yang sibuk. Setiap pesanan pelanggan diibaratkan sebagai sebuah event. Alih-alih menunggu satu pesanan selesai sepenuhnya (yang akan memperlambat layanan), pelayan menerima pesanan dari banyak pelanggan (menambahkan event ke callback queue) dan memprosesnya satu per satu ketika sumber daya tersedia.
Dengan kata lain, event loop secara konstan memonitor call stack (tumpukan panggilan fungsi) dan callback queue. Jika call stack kosong, event loop akan mengambil event pertama dari callback queue dan memindahkannya ke call stack untuk dieksekusi. Proses ini berulang terus menerus, memastikan bahwa JavaScript tetap responsif bahkan ketika berhadapan dengan operasi yang membutuhkan waktu lama.
Bagaimana Event Loop Bekerja?
Bayangkan sebuah restoran dengan satu pelayan dan banyak meja. Pelayan tersebut akan menerima pesanan dari setiap meja (mewakili thread utama JavaScript), tetapi alih-alih menunggu makanan selesai dimasak di setiap meja, ia akan mencatat pesanan (menambahkan tugas ke call stack) dan mengirimkannya ke dapur (Web API seperti setTimeout atau fetch).
Sambil menunggu makanan dari meja sebelumnya matang, pelayan akan melayani meja lain dan menerima pesanan mereka. Ketika makanan dari dapur siap (operasi asinkron selesai), ia akan diletakkan di meja antrian (callback queue).
Di sinilah peran Event Loop dimulai. Ia bertugas untuk secara terus menerus memeriksa apakah call stack kosong dan callback queue memiliki tugas yang menunggu. Jika call stack kosong, Event Loop akan mengambil tugas pertama dari callback queue dan memindahkannya ke call stack untuk dieksekusi.
Proses ini berulang terus menerus, memastikan bahwa JavaScript tetap responsif meskipun ada operasi yang berjalan lama. Event Loop menjamin bahwa kode di callback queue hanya akan dieksekusi saat thread utama kosong, mencegah terjadinya blocking dan menjaga kelancaran aplikasi.
Memahami Callback Queue dan Microtask Queue
Dalam JavaScript, mekanisme asynchronous seperti setTimeout dan Promise bergantung pada dua antrian penting: Callback Queue dan Microtask Queue. Keduanya berperan dalam menentukan eksekusi kode asynchronous setelah call stack kosong.
Callback Queue, sesuai namanya, menampung fungsi-fungsi callback dari operasi asynchronous seperti setTimeout atau event listener. Setiap kali call stack kosong, Event Loop akan memeriksa Callback Queue. Jika ada callback yang siap dieksekusi, callback tersebut akan dipindahkan ke call stack untuk dijalankan.
Microtask Queue memiliki prioritas lebih tinggi daripada Callback Queue. Antrian ini menampung tugas-tugas seperti promise callback (then/catch/finally) dan fungsi-fungsi yang dijadwalkan dengan queueMicrotask(). Setelah call stack kosong, Event Loop akan memprioritaskan Microtask Queue dan mengeksekusi semua tugas di dalamnya sebelum beralih ke Callback Queue.
Sebagai ilustrasi, bayangkan Anda sedang memasak dan menunggu air mendidih (setTimeout). Sambil menunggu, Anda juga ingin mengiris bawang (Promise). Mengiris bawang akan selesai lebih dulu (Microtask Queue) dan langsung Anda masukkan ke dalam panci. Air mendidih kemudian (Callback Queue) dan Anda baru akan memasak setelahnya.
Memahami perbedaan dan interaksi antara Callback Queue dan Microtask Queue sangat krusial dalam menguasai alur eksekusi asynchronous di JavaScript dan membangun aplikasi yang responsif dan efisien.
Contoh Penerapan Event Loop dalam Kode JavaScript
Mari kita lihat contoh konkrit bagaimana Event Loop bekerja dalam JavaScript. Perhatikan cuplikan kode berikut:
console.log("Pertama"); setTimeout(() => { console.log("Kedua"); }, 0); console.log("Ketiga");
Meskipun setTimeout
diatur dengan delay 0 milidetik, output yang dihasilkan di konsol bukanlah “Pertama”, “Kedua”, “Ketiga”. Mengapa? Karena Event Loop.
1. Pertama, console.log("Pertama")
dijalankan dan “Pertama” ditampilkan di konsol. 2. Selanjutnya, setTimeout
dipanggil. Fungsi di dalamnya (yang akan menampilkan “Kedua”) ditambahkan ke Web API, sebuah lingkungan terpisah dari Call Stack. 3. Tanpa menunggu setTimeout
, console.log("Ketiga")
dijalankan, menampilkan “Ketiga” di konsol. 4. Setelah Call Stack kosong, Event Loop mengecek Callback Queue. Fungsi dalam setTimeout
, yang telah selesai menunggu di Web API, kini berada di Callback Queue. 5. Event Loop memindahkan fungsi tersebut ke Call Stack. 6. Akhirnya, console.log("Kedua")
dijalankan dan “Kedua” ditampilkan di konsol.
Output akhir di konsol akan menjadi:
Pertama Ketiga Kedua
Contoh ini menunjukkan bahwa Event Loop memprioritaskan kode yang ada di Call Stack. Kode asynchronous, seperti setTimeout
, dijalankan setelah kode synchronous selesai, bahkan jika delay diatur ke 0. Pemahaman akan Event Loop sangat krusial dalam pengembangan JavaScript, terutama ketika berurusan dengan operasi asynchronous yang banyak digunakan dalam pengembangan web modern.