Memahami Asynchronous Programming: Kenapa JavaScript Tidak "Nge-freeze"?
Bayangkan Anda Sedang di Restoran
Ketika Anda memesan makanan di restoran, apakah pelayan berdiri diam menunggu di depan dapur sampai makanan Anda selesai dimasak, sebelum melayani meja lain? Tentu tidak—pelayan akan mencatat pesanan Anda, meneruskannya ke dapur, lalu melayani meja lain sambil menunggu makanan Anda matang. Begitu makanan siap, pelayan baru mengantarkannya ke meja Anda.
Ini persis konsep asynchronous programming: alih-alih menunggu (blocking) satu tugas selesai sebelum mengerjakan yang lain, program bisa "menitipkan" tugas yang lama (seperti membaca file, request ke server, atau query database) dan lanjut mengerjakan hal lain sambil menunggu.
Synchronous vs Asynchronous
Synchronous (blocking): setiap baris kode harus selesai dieksekusi sebelum baris berikutnya berjalan.
console.log("1. Mulai masak nasi")masakNasi() // Bayangkan ini butuh waktu 20 menit, dan program BERHENTI TOTAL menungguconsole.log("2. Nasi matang, lanjut potong sayur")
Kalau masakNasi() bersifat synchronous dan butuh 20 menit, seluruh program—termasuk hal-hal yang tidak berhubungan sama sekali dengan memasak nasi—akan macet total selama 20 menit itu.
Asynchronous (non-blocking): tugas yang lama dijalankan di "latar belakang", dan program lanjut mengerjakan baris berikutnya tanpa menunggu.
console.log("1. Mulai masak nasi")masakNasiAsync().then(() => {console.log("3. Nasi matang!")})console.log("2. Sambil nunggu, potong sayur dulu")// Output:// 1. Mulai masak nasi// 2. Sambil nunggu, potong sayur dulu// 3. Nasi matang! <- muncul belakangan, setelah "masak" selesai
Kenapa Ini Penting untuk JavaScript?
JavaScript berjalan di satu thread saja (akan dibahas lebih detail di artikel lain soal thread & concurrency). Kalau setiap operasi bersifat blocking, maka satu request yang lambat ke server bisa membuat seluruh halaman web membeku—tombol tidak bisa diklik, scroll tidak jalan, semuanya diam sampai request itu selesai.
Untungnya, browser (dan Node.js) menyediakan Event Loop yang menangani operasi-operasi lambat (network request, file I/O, timer) di luar thread utama, lalu mengembalikan hasilnya ke thread utama saat sudah selesai—tanpa pernah memblokir eksekusi kode yang lain.
Tiga Cara Menulis Kode Asynchronous di JavaScript
1. Callback (cara paling lama)
getDataUser(userId, function(user) {console.log("Dapat data user:", user)})
Masalahnya: kalau butuh beberapa operasi asynchronous berurutan, kode jadi bersarang dalam-dalam—sering disebut "callback hell".
2. Promise
getDataUser(userId).then(user => getDataPosts(user.id)).then(posts => console.log("Dapat posts:", posts)).catch(err => console.error("Ada error:", err))
Promise mewakili "janji" bahwa suatu nilai akan tersedia di masa depan (baik berhasil dengan .then(), atau gagal dengan .catch()).
3. Async/Await (yang paling banyak dipakai sekarang)
async function tampilkanDataUser(userId) {try {const user = await getDataUser(userId)const posts = await getDataPosts(user.id)console.log("Dapat posts:", posts)} catch (err) {console.error("Ada error:", err)}}
async/await sebenarnya cuma "gula sintaks" (syntactic sugar) di atas Promise—tapi terasa jauh lebih mudah dibaca karena mirip kode synchronous biasa, padahal di baliknya tetap non-blocking.
Kesalahan Umum Pemula
- Lupa pakai
await—hasilnya Anda dapat objekPromiseyang belum "terbuka", bukan nilai aslinya. - Menaruh
awaitdi dalam loop yang seharusnya bisa paralel—misalnya memanggil 10 API satu per satu denganawaitdi dalamforloop, padahal bisa memakaiPromise.all()supaya semuanya berjalan bersamaan.
// Lambat: menunggu satu per satu secara berurutanfor (const id of userIds) {const user = await getDataUser(id) // Nunggu selesai dulu, baru lanjut ke id berikutnya}// Lebih cepat: semua request dikirim bersamaanconst users = await Promise.all(userIds.map(id => getDataUser(id)))
Kesimpulan
Asynchronous programming bukan soal "menjalankan banyak hal sekaligus secara paralel" (itu topik concurrency/thread, beda artikel)—tapi soal tidak membuat program menunggu sia-sia ketika ada operasi yang lambat. Dengan async/await, kode asynchronous bisa ditulis hampir seperti kode biasa, tapi tetap menjaga aplikasi Anda tetap responsif.
Artikel Terkait
Diskusi Pembaca (1)
Analogi restoran-nya bikin langsung ngerti. Makasih kak!
