What are Web Workers?
Web Workers let you run JavaScript in a background thread, separate from the main UI thread. This means heavy computations won't freeze the page. The worker runs in its own scope — it can't access the DOM, but it can make network requests and use IndexedDB.
// main.js
const worker = new Worker("worker.js");
worker.postMessage({ data: largeArray });
worker.onmessage = (event) => {
console.log("Result:", event.data);
};
// worker.js
self.onmessage = (event) => {
const result = processLargeData(event.data);
self.postMessage(result);
};
When to Use Web Workers
Use workers for CPU-intensive tasks like image processing, complex calculations, data sorting, or parsing large JSON files. If a task takes more than ~16ms, it will cause jank on the main thread.
// worker.js — sorting a huge array
self.onmessage = (event) => {
const { array } = event.data;
// This might take a while
const sorted = array.sort((a, b) => a - b);
self.postMessage(sorted);
};
Communication via postMessage
Workers and the main thread communicate through messages. Data is copied (structured clone), not shared. You can also transfer binary data like ArrayBuffers for better performance.
// Transfer an ArrayBuffer to the worker
const buffer = new ArrayBuffer(1024 * 1024);
worker.postMessage({ buffer }, [buffer]);
// buffer is now neutered (empty) on the main thread
Handling Errors
Workers can throw errors just like main thread code. Always set up error handlers to catch problems in the worker.
const worker = new Worker("worker.js");
worker.onerror = (error) => {
console.error("Worker error:", error.message);
};
Summary
Web Workers keep your UI responsive by offloading heavy work to background threads. They communicate via postMessage and can't access the DOM. Use them for any CPU-intensive task.