
Asynchronous Javascript 1 - Pengenalan
Konsep asynchronous dalam pemrograman Javascript sangat penting karena memungkinkan aplikasi berjalan responsif dan cepat, meskipun ada proses lainnya yang sedang berjalan secara bersamaan.
Banyak aktivitas di browser yang bisa memakan waktu cukup lama untuk dapat diselesaikan, seperti:
- Mengambil data dari backend dengan fungsi
fetch()
- Melakukan iterasi atau kalkulasi yang berat
Apabila aktivitas memakan waktu ini dijalankan secara synchronous, tentu pengalaman pengguna website atau aplikasi menjadi tidak optimal, karena harus menunggu suatu proses selesai, sebelum menjalankan proses selanjutnya.
Disini Saya akan mulai membahas dari pemrograman synchronous agar dapat lebih memahami mengapa pemrograman asynchronous menjadi suatu kebutuhan.
Pemrograman synchronous
Javascript adalah bahasa yang secara default menjalankan program secara synchronous. Artinya, kode program akan dieksekusi secara berurutan dari awal sampai akhir, baris perbaris.
Proses synchronous kadang juga disebut blocking, karena eksekusi baris kode akan ter-block, sampai baris kode sebelumnya selesai dieksekusi. Lihat kode berikut:
Eksekusi kode diatas pasti menghasilkan urutan yang sama, berapa kalipun dijalankan. Output “Halo Juga!” tidak mungkin muncul pertama kali. Karena tiap baris kode dieksekusi setelah kode sebelumnya selesai secara berurutan.
Pemrograman asynchronous
Sifat alami Javascript yang mengeksekusi kode program secara synchronous akan butuh perlakuan berbeda saat menemui program yang berat, dan prosesnya memakan waktu panjang. Perhatikan kode pada editor berikut
- Tidak memunculkan error-error tertentu, seperti ReferenceError saat mengakses variabel yang belum didefinisikan
- Melakukan batching, sehingga jika ada eksekusi kode yang lama, maka log tidak akan mencerminkan delay dari eksekusi yang lama tersebut.
Kode yang dieksekusi diatas merupakan contoh program yang memerlukan waktu cukup lama tergantung kecepatan komputer. Iterasi yang lebih banyak lagi bahkan bisa menjadikan browser tidak responsif dan crash.
Efeknya program selanjutnya baru akan dijalankan setelah proses pertama selesai, dan ini tidak efektif.
Jika dianalogikan dengan aktifitas sehari-hari, misal di sebuah restoran ada 5 meja. Untuk dapat makan, pelanggan harus melalui 3 buah proses: memesan, pesanan dimasak, pesanan diantar ke meja. Mana yang lebih efektif:
- pesanan dilakukan, dimasak, dan diantar berurutan untuk setiap meja secara berurutan.
- atau, pesanan dikumpulkan dahulu, lalu dimasak (jika ada menu yang sama bisa sekaligus), lalu diantar menurut makanan yang sudah tersedia.
Tentu opsi kedua jauh lebih efektif, inilah salah satu contoh proses asynchronous di dunia nyata.
Kode sebelumnya dapat dijadikan asynchronous dengan bantuan fungsi setTimeout()
, sehingga tidak mem-blocking kode baris selanjutnya.
- Tidak memunculkan error-error tertentu, seperti ReferenceError saat mengakses variabel yang belum didefinisikan
- Melakukan batching, sehingga jika ada eksekusi kode yang lama, maka log tidak akan mencerminkan delay dari eksekusi yang lama tersebut.
fungsi setTimeout()
bekerja dengan mengagendakan suatu kode program (disebut callback) untuk dieksekusi setelah waktu tertentu. Callback yang dijadikan argumen disimpan dahulu untuk pada suatu antrian, agar proses lainnya dapat berjalan langsung.
Sekilas tentang bagaimana Javascript bekerja
Javascript adalah bahasa yang single-threaded, ia hanya bisa menjalankan satu tugas dalam satu waktu (synchronous). Lalu bagaimana Javascript bisa menjalankan proses asynchronous?
Agar dapat memiliki gambaran lebih jelas tentang cara kerja proses asynchronous, mari menjelajah sedikit lebih dalam ke bagaimana Javascript bekerja. Perhatikan ilustrasi berikut.
Ilustrasi diatas merupakan gambaran sederhana untuk setiap komponen yang berperan menjalankan program Javascript di browser (javascript runtime). Berikut adalah penjelasan singkat masing-masing komponen
- JavaScript Engine adalah perangkat lunak yang mengeksekusi kode JavaScript. Mesin ini mengkompilasi kode JavaScript menjadi kode mesin yang dapat dijalankan oleh CPU. Selain itu, mesin JavaScript juga mengelola memori dan melakukan optimasi (contoh v8, SpiderMonkey).
- Heap adalah area memori yang digunakan untuk menyimpan data berupa Objek, array, dan fungsi.
- Call stack adalah struktur data bertumpuk yang berisi invokasi fungsi dan mengelola urutannya. Setiap kali sebuah fungsi dipanggil (invoke), sebuah frame baru ditambahkan ke tumpukan. Ketika fungsi selesai dijalankan, frame tersebut dihapus.
- Web API adalah kumpulan API yang disediakan oleh browser yang memungkinkan JavaScript berinteraksi dengan elemen web (DOM). Contoh termasuk
setTimeout
,fetch
, event handling, Geolokasi, dan lainnya. - Task queue adalah tempat menyimpan proses-proses asynchronous saat call stack masih terisi.
- Event loop adalah mekanisme yang mengatur eksekusi kode asynchronous. Mekanisme ini bekerja dengan memeriksa apakah call stack kosong, jika ya dan ada proses yang tersimpan di queue maka akan dipindahkan ke call stack untuk dieksekusi.
Saya akan menggunakan kode terakhir yang sudah dicoba sebelumnya, untuk memperagakan bagaimana kode berjalan didalam Javascript runtime.
function heavyComputation() {
let sum = 0;
const iterations = 10000;
for (let i = 0; i < iterations; i++) {
for (let j = 0; j < iterations; j++) {
sum += Math.sqrt(i * j) * Math.cos(j);
}
}
console.log("calculation finished, number is: " + sum);
}
console.log("Starting heavy computation...");
setTimeout(heavyComputation);
console.log("code finished");
Perhatikan simulasi interaktif kode diatas pada widget berikut. Gunakan tombol arah kanan dan kiri untuk navigasi eksekusi kode, dan reset untuk mengulang.
Javascript Engine
Heap
Call Stack
Event Loop
Web API
API
Task Queue
Sudah lebih jelas bukan bagaimana sebuah kode program Javascript berjalan? kalau kamu ingin coba simulasi yang lebih dinamis, bisa cek tools ini.
Bahasa Single Threaded
Ketika membaca-baca di internet, kamu mungkin pernah menemukan pernyataan bahwa bahasa seperti Jacascript dan Python adalah bahasa single threaded.
Thread adalah unit eksekusi terkecil dari suatu proses (program yang dieksekusi) yang berjalan pada prosesor. Setiap thread memiliki call stack sendiri, yang berisi konteks eksekusi program yang sedang berjalan.
Karena JavaScript adalah bahasa single-thread, JavaScript hanya memiliki satu call stack, yang berarti JavaScript hanya dapat menjalankan kode secara synchronous. Namun Javascript memiliki mekanisme event-loop yang memungkinkannya mengerjakan suatu program secara asynchronous.
Bahasa multi-thread seperti Java dan C++ memiliki kemampuan menjalankan program secara paralel dengan membagi eksekusi program kedalam beberapa thread yang memiliki call stack nya masing-masing.
JavaScript dirancang untuk menjadi bahasa single-thread karena lingkungan di mana ia dijalankan – browser. Ketika JavaScript dibuat pada tahun 1995, penggunaan utamanya adalah menambahkan interaktivitas ke halaman web statis. Pada saat itu, komputer jauh lebih lambat dibandingkan sekarang, dan jumlah daya pemrosesan yang tersedia terbatas. Untuk menjaga bahasa tetap sederhana dan efisien, JavaScript dibuat single-threaded.
Quiz
Sebelum lanjut ke pembahasan berikutnya tentang Callback, kerjakan quiz berikut. Tebak apa output yang akan keluar di console.