Dedicated Web Workers
Creating a worker
Section titled “Creating a worker”new Worker(url) takes a URL pointing to a JavaScript file. The browser downloads that file and runs it in an isolated background thread. In these lessons, instead of hosting a separate file, we generate the URL on the fly from a Blob — this keeps everything self-contained and runnable inline.
// worker.js (separate file)self.onmessage = function(e) { const result = heavyCompute(e.data); self.postMessage(result);};
// main.jsconst worker = new Worker('/worker.js');worker.onmessage = function(e) { console.log('result:', e.data); };worker.postMessage(inputData);The four key APIs
Section titled “The four key APIs”worker.postMessage(data)— send data to the worker from the main threadworker.onmessage = fn— receive data from the worker on the main threadself.onmessage = fn— (inside the worker) receive data from the main threadself.postMessage(data)— (inside the worker) send a result back to the main threadworker.terminate()— immediately stop the worker from the main thread; the worker gets no warning
Inline worker via Blob URL
Section titled “Inline worker via Blob URL”Instead of a separate file, you can define the worker source as a string, wrap it in a Blob, and convert that to an object URL with URL.createObjectURL. The resulting URL looks like blob:https://example.com/uuid and behaves exactly like a hosted file URL. After the worker is no longer needed, call URL.revokeObjectURL(url) to free the memory.
Runnable: computing off-thread
Section titled “Runnable: computing off-thread”The worker below sums all integers from 1 to N. With N = 1 000 000, this is a non-trivial loop that would briefly block the main thread if run inline — here it runs in a background thread instead.
Trade-offs
Section titled “Trade-offs”| Option | Benefit | Cost |
|---|---|---|
| Processing in a Web Worker | True parallelism — a background thread separate from the main thread keeps the UI responsive during heavy work | Communication cost via postMessage (structured clone), plus the overhead of creating/destroying the worker |
| Processing directly on the main thread | Simple, immediate DOM access, no cross-thread communication cost | Heavy work blocks the UI thread, causing the page to freeze or drop frames |
| Inline worker via a Blob URL | No separate file to host — code lives in one place, easy to deploy | Harder to debug than a real file since there’s no straightforward source map or breakpoint |
Common mistakes
Section titled “Common mistakes”- Expecting a worker to access the DOM — a worker has no
window,document, or any DOM API at all. This is the most common beginner misunderstanding;postMessagethe result back and let the main thread handle the DOM instead. - Forgetting to call
worker.terminate()— a worker that’s never terminated stays in memory and keeps consuming CPU even after its work is done, causing a memory leak, especially if you keep creating new workers. - Using a worker for short work that takes less than a few milliseconds — the cost of creating the worker and round-tripping a
postMessageoutweighs the benefit. Reserve workers for work that’s long enough to justify the overhead.