Web Workers and Multithreading
Web Workers & Multithreading in JavaScript
Offloading CPU-bound tasks, postMessage communication, Transferable objects, and concurrency.
The Chief Executive and the Remote Back-Office
JavaScript is single-threaded on its main thread. Web Workers provide true OS-level background threads, allowing CPU-intensive computations to run without degrading UI responsiveness.
Main Thread vs Worker Thread
The main thread handles DOM, user inputs, and CSS rendering. Workers run in separate OS threads with their own global scope (`self`), execution context, and event loop.
Asynchronous Message Passing
Communication uses `worker.postMessage(data)` and `self.onmessage = (e) => {}`. Data passed is serialized via the Structured Clone algorithm.
Zero-Copy Transferable Objects
For massive datasets (ArrayBuffers, ImageBitmaps), transferring ownership `postMessage(buffer, [buffer])` transfers memory pointers with zero copying overhead.
Worker Limitations
Workers CANNOT access the DOM, `window`, `document`, or `parent`. They CAN use `fetch`, `setTimeout`, `crypto`, `IndexedDB`, and `importScripts()` / ESM imports.
Main thread dispatching heavy calculations to a Web Worker:
// --- Inside main.js ---
// const worker = new Worker("worker.js", { type: "module" });
//
// worker.postMessage({ command: "CALCULATE_PRIME", count: 1000000 });
//
// worker.onmessage = (e) => {
// console.log("Result received from background thread:", e.data.result);
// };
// --- Inside worker.js (Background Thread) ---
// self.onmessage = (e) => {
// const { command, count } = e.data;
// if (command === "CALCULATE_PRIME") {
// const result = computePrimes(count); // CPU intensive task
// self.postMessage({ result });
// }
// };
// Simulated Message Exchange
console.log("Main Thread: UI stays responsive at 60fps.");
setTimeout(() => {
console.log("Worker Thread: Heavy calculation complete: 78498 primes found.");
}, 100);
Main Thread: UI stays responsive at 60fps.
Worker Thread: Heavy calculation complete: 78498 primes found.
Attempting DOM Manipulation in Workers
The Risk: Calling `document.getElementById()` inside a worker throws `ReferenceError: document is not defined`.
The Fix: Workers can only compute data. Send computed results back to the main thread via `postMessage` to update the DOM.
Structured Clone Overhead on Huge Data
The Risk: Passing multi-megabyte objects repeatedly across `postMessage` causes serialization lag.
The Fix: Use Transferable objects (`ArrayBuffer`) or `SharedArrayBuffer` with `Atomics` for zero-copy memory transfers.
- ✓ Web Workers run in true separate OS background threads.
- ✓ Workers have NO access to the DOM or window object.
- ✓ Communicate asynchronously via `postMessage()` and `onmessage`.
- ✓ Use Transferable Objects (`ArrayBuffer`) for zero-copy high-speed data transfer.
- ✓ Essential for image/video processing, cryptography, audio synthesis, and heavy parsing.