You will be able to move CPU-heavy JavaScript work off the main thread using a Web Worker, communicate with messages, and know when this pattern is appropriate.
What it is
A Web Worker is a browser API that runs JavaScript in a background thread, separate from the main thread that handles rendering and user input. The mental model is a helper process: you send it data, it computes, then sends a result back. Workers cannot touch the DOM, so they are best for pure computation or data processing. Related terms include dedicated worker, shared worker, message passing, postMessage, onmessage, and terminate.
Why it matters
- Keeps the interface responsive while large loops, parsing, or image processing run in the background.
- Prevents long tasks from blocking clicks, scrolling, and animations.
- Lets you isolate heavy code so errors can be reported without freezing the page.
- Works well for data transformation, search, sorting, compression, or simulation.
Syntax or steps
- Create a separate JavaScript file, such as
worker.js, that contains the background code. - Instantiate it on the main thread with
new Worker("worker.js"). - Send data to the worker using
postMessage. - Listen for results with
onmessageoraddEventListener("message"). - Call
terminatewhen the worker is no longer needed.
Example
// main.js
const worker = new Worker("worker.js");
worker.postMessage({ type: "sum", start: 1, end: 1000000 });
worker.onmessage = (event) => {
console.log("Result:", event.data);
worker.terminate();
};
worker.onerror = (event) => {
console.error("Worker error:", event.message);
};
// worker.js
self.onmessage = (event) => {
const { type, start, end } = event.data;
if (type === "sum") {
let total = 0;
for (let i = start; i <= end; i++) {
total += i;
}
self.postMessage(total);
}
};
In main.js, the page creates a worker and sends it a message containing the work to do. In worker.js, the worker receives the message, performs the calculation, and posts the result back. The main thread remains free to respond to user input while the worker runs.
Common mistakes
- Trying to access the DOM from a worker. Workers have no
documentorwindow. Keep DOM updates on the main thread. - Assuming variables are shared. Messages are copied between threads. Use
postMessageto send data and receive results. - Forgetting to terminate workers. A worker that is no longer needed can keep running. Call
worker.terminate()when done. - Using a worker for tiny tasks. Creating and messaging a worker has overhead. Use it only when the work is large enough to block the main thread.
When to use it
| Need | Use | Why |
|---|---|---|
| Wait for network or file I/O | async / await |
These operations are already non-blocking on the main thread. |
| Heavy CPU loop | Web Worker | The work runs on a separate thread and keeps the UI responsive. |
| Small delayed UI update | setTimeout or requestAnimationFrame |
Less overhead than starting a worker. |
Practice
Guided exercise: Create a worker that receives an array of numbers and returns their average. Send [10, 20, 30] from the main thread and log the result.
Expected output: 20
Challenge: Modify the worker so it can handle two message types: "average" and "max". Hint: use event.data.type to choose the calculation.
Quick check
Question: Why can’t a Web Worker directly update the page HTML?
Answer: Because workers run on a background thread and do not have access to the DOM. DOM updates must happen on the main thread.
Summary
Web Workers let JavaScript run heavy computation off the main thread while keeping the user interface responsive. They communicate through messages, not shared variables, and are best for CPU-bound tasks rather than simple delays or network requests.