JavaScript runs on one main thread, and a long calculation freezes the page: no clicks, no scrolling, no animation. A Web Worker runs code in a separate background thread, so the page stays responsive.
> Workers need separate files (or blob URLs) and a real page, so this lesson shows the code to use in your own project.
The two files
// runs in the background thread
self.addEventListener("message", event => {
const n = event.data;
let sum = 0;
for (let i = 0; i <= n; i++) sum += i; // heavy work
self.postMessage(sum); // send the result back
});
const worker = new Worker("worker.js");
worker.addEventListener("message", event => {
console.log("Result from the worker:", event.data);
});
worker.postMessage(1_000_000_000); // send work
console.log("The page stays responsive meanwhile");
Communication is by messages (postMessage and the message event). Data is copied between threads with the structured clone algorithm (the same one structuredClone() uses), so you cannot share live objects or functions.
What a worker cannot do
- No DOM. There is no
documentorwindowin a worker. It cannot change the page directly. It sends results to the main thread, which updates the page. - No access to the main thread’s variables.
It can use: fetch, timers, IndexedDB, WebSocket, importScripts() or module imports, console, and most computation.
Module workers
const worker = new Worker("worker.js", { type: "module" });
Lets the worker use import and export.
Errors and stopping
worker.addEventListener("error", event => console.error("Worker error:", event.message));
worker.terminate(); // stop it from the main thread
// inside a worker: self.close();
Transferring big data
Large buffers can be transferred instead of copied, which is instant:
const buffer = new ArrayBuffer(10_000_000);
worker.postMessage(buffer, [buffer]); // after this, `buffer` is no longer usable here
When to use workers
Use a worker for CPU-heavy work: parsing big files, image processing, complex calculations, compressing, searching a large data set.
Do not use one for waiting: fetch and timers do not block the main thread, so a worker adds nothing.
Other kinds of workers
- Service Workers: sit between the page and the network (offline support, push notifications).
- Shared Workers: shared by several tabs.
- Worklets: specialised, for audio and painting.
Costs
Starting a worker has a cost, and messaging adds overhead. For small tasks, a worker is slower than just doing the work. Measure first (Performance).