Explorer
JavaScript

Web Workers and Multithreading

JavaScript Theory & Concepts

Web Workers & Multithreading in JavaScript

Offloading CPU-bound tasks, postMessage communication, Transferable objects, and concurrency.

📖 The Story & Real-World Analogy

The Chief Executive and the Remote Back-Office

"Imagine a corporate CEO (the Main JS Thread) greeting VIP clients at the front lobby. If the CEO sat down on the lobby floor with a 1,000-page accounting ledger to calculate quarterly tax matrices, the CEO could not shake hands, open doors, or speak (the UI freezes and drops to 0 fps!). Instead, the CEO photocopies the ledger and sends it to the dedicated Back-Office Analytics Team (Web Worker). The worker crunches the math in their own private office and emails the final result back to the CEO. The CEO stays completely free to greet visitors with zero interruptions!"

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.

⚙️ How It Works Under The Hood (Step-by-Step)
1

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.

2

Asynchronous Message Passing

Communication uses `worker.postMessage(data)` and `self.onmessage = (e) => {}`. Data passed is serialized via the Structured Clone algorithm.

3

Zero-Copy Transferable Objects

For massive datasets (ArrayBuffers, ImageBitmaps), transferring ownership `postMessage(buffer, [buffer])` transfers memory pointers with zero copying overhead.

4

Worker Limitations

Workers CANNOT access the DOM, `window`, `document`, or `parent`. They CAN use `fetch`, `setTimeout`, `crypto`, `IndexedDB`, and `importScripts()` / ESM imports.

💻 Interactive Code Walkthrough

Main thread dispatching heavy calculations to a Web Worker:

JAVASCRIPT
// --- 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);
Console Output:
CODE
Main Thread: UI stays responsive at 60fps.
Worker Thread: Heavy calculation complete: 78498 primes found.
⚠️ Common Pitfalls & Interview Traps
Trap
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.

Trap
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.

⚡ 30-Second Quick Revision Cheat Sheet (TL;DR)
  • ✓ 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.

Finished this lesson?

Mark this chapter complete to update your learning streak and unlock the next lesson.