Web Worker: Komputasi Tanpa Bikin Freeze
Kenapa komputasi berat membuat UI macet, dan cara memindahkannya ke thread latar dengan Web Worker lewat Blob URL dan postMessage.
Kenapa Worker Ada: Masalah UI Freeze
JavaScript di browser berjalan dalam SATU thread utama. Thread yang sama menggambar tombol, merespons klik, DAN menjalankan kodemu. Jadi kalau kodemu melakukan perhitungan berat yang memakan 3 detik, selama 3 detik itu browser tidak bisa merespons apapun: tombol tidak bisa diklik, scroll macet, animasi berhenti. Inilah yang disebut UI freeze, dan pengguna menganggapnya sebagai aplikasi yang rusak.
// JANGAN lakukan ini di thread utama untuk data besar!
function jumlahRaksasa(n) {
let total = 0;
for (let i = 1; i <= n; i++) total += i;
return total;
}
console.log(jumlahRaksasa(500000000)); // UI macet selama menghitungWeb Worker adalah solusinya: thread latar terpisah yang menjalankan JavaScript tanpa mengganggu thread utama. UI tetap responsif sementara worker sibuk menghitung.
Membuat Worker dari Blob URL
Worker biasanya butuh file JS terpisah, tapi trik Blob URL memungkinkan semuanya tetap dalam SATU file, praktis untuk latihan dan playground.
// 1. tulis kode worker sebagai string
const kodeWorker = `
onmessage = (e) => {
const n = e.data;
let total = 0;
for (let i = 1; i <= n; i++) total += i;
postMessage(total); // kirim hasil kembali
};
`;
// 2. ubah string menjadi URL yang bisa dimuat worker
const blob = new Blob([kodeWorker], { type: "text/javascript" });
const worker = new Worker(URL.createObjectURL(blob));
// 3. komunikasi dua arah
worker.onmessage = (e) => {
console.log("Hasil dari worker:", e.data);
worker.terminate(); // bebaskan memori setelah selesai
};
console.log("Mengirim tugas, UI tetap responsif...");
worker.postMessage(500000000);Pola komunikasinya selalu sama: postMessage untuk mengirim, onmessage untuk menerima. Thread utama dan worker TIDAK berbagi variabel, mereka hanya bertukar pesan.
Contoh Nyata: Filter Foto
Bayangkan aplikasi edit foto: menerapkan filter ke gambar 12 megapiksel berarti mengolah 36 juta nilai piksel. Di thread utama, pratinjau akan macet total. Polanya di dunia nyata:
// thread utama: ambil data piksel, kirim ke worker
const dataGambar = ctx.getImageData(0, 0, kanvas.width, kanvas.height);
worker.postMessage(dataGambar.data);
// di dalam worker: proses piksel, kirim balik
onmessage = (e) => {
const piksel = e.data;
for (let i = 0; i < piksel.length; i += 4) {
const abu = (piksel[i] + piksel[i+1] + piksel[i+2]) / 3;
piksel[i] = piksel[i+1] = piksel[i+2] = abu; // efek grayscale
}
postMessage(piksel);
};Selama worker mengolah piksel, pengguna tetap bisa menggeser slider dan mengklik tombol.
Aturan Main Worker
Pertama, worker TIDAK bisa mengakses DOM (tidak ada document atau window): ia hanya untuk komputasi murni. Kedua, data yang dikirim lewat postMessage di-copy (structured clone), bukan dibagi, jadi mengirim objek raksasa bolak-balik ada biayanya. Ketiga, selalu panggil worker.terminate() kalau worker sudah tidak dibutuhkan agar tidak bocor memori.
Jebakan Umum
Kesalahan paling umum adalah mengira worker membuat kode lebih cepat. Tidak: satu perhitungan yang sama memakan waktu yang sama, worker hanya memindahkannya agar tidak menghalangi UI. Untuk tugas ringan, overhead membuat worker justru lebih lambat daripada menghitung langsung. Pakai worker untuk komputasi yang benar-benar berat (ratusan milidetik ke atas): enkripsi, parsing file besar, perhitungan statistik, atau pemrosesan gambar.
Catatan teknis: Pesan antar thread disalin dengan algoritma structured clone yang menangani objek, array, Date, Map, hingga ArrayBuffer (yang bahkan bisa di-transfer tanpa copy memakai transferable objects). Fungsi dan DOM node tidak bisa dikirim. Di balik layar, inilah model concurrency JavaScript: satu thread utama plus worker yang berkomunikasi lewat message passing, tanpa shared memory yang rawan race condition.
export default function App(): JSX.Element { return <h1>Hello world</h1> }
Tantangan
Hitung Bilangan Prima di Worker
Mencari bilangan prima sampai angka besar adalah contoh klasik komputasi berat yang di dunia nyata dijalankan di latar (misalnya saat aplikasi memproses data sambil pengguna tetap berinteraksi). Tantanganmu: buat worker via Blob URL yang menerima angka N lewat postMessage, menghitung berapa banyak bilangan prima dari 2 sampai N, lalu mengembalikan hasilnya. Thread utama hanya mengirim N dan menampilkan hasil.
<!doctype html> <html> <head> <meta charset="utf-8" /> </head> <body> <h1>Halo JS</h1> <p>Buka console preview untuk melihat output.</p> <script src="index.js"></script> </body> </html>