A dedicated worker runs JavaScript outside the page's main thread and communicates by messages. It does not receive the page DOM, so it is well suited to parsing, summarizing, or transforming data rather than updating visible controls directly. Message payloads are commonly copied with structured cloning; transferable buffers can move ownership instead, after which the sender cannot keep using the transferred buffer. Put a request ID or generation number on each job so an old result cannot overwrite a newer route. Cancellation requires an explicit protocol or worker termination; posting a cancel message cannot interrupt a synchronous worker loop until that loop yields.
Workers, Messages, Transfer, and Cancellation
Working case
The case page accepts a large local measurement file and computes a preview. Parsing on the main thread makes the note field lag. A worker can process the file bytes and send back a summary for case 47. Before it finishes, the reviewer opens case 62. The page must ignore the old result even if the worker completes successfully. If the bytes are transferred for speed, the main thread must not expect to reread the same buffer after posting it. A new job either uses new bytes or an intentional copy.
Implementation boundary
// Page module
const parseWorker = new Worker(new URL("./case-parser.worker.js", import.meta.url), { type: "module" });
let currentJobId = 0;
function parseCaseBytes(caseBytes) {
const jobId = ++currentJobId;
parseWorker.postMessage({ jobId, bytes: caseBytes }, [caseBytes]);
}
parseWorker.onmessage = event => {
if (event.data.jobId !== currentJobId) return;
renderCaseSummary(event.data.summary);
};The page sketch transfers an ArrayBuffer, not an arbitrary typed-array view, and uses a job ID to reject obsolete results. The worker file must validate message shape, perform bounded parsing, and return either a result or a classified error with the same job ID. Route cleanup should terminate or reuse the worker deliberately and remove stale handlers. A job ID stops old results from changing UI, but it does not stop wasted CPU. If cancellation matters, split worker work into chunks that can receive a cancel message or terminate the worker and recreate it.
Cost and boundaries
Creating a worker and loading its module takes time and memory. Structured cloning a large object also takes time and memory; transferring a buffer can avoid the copy but detaches it from the sender. For tiny calculations, the communication overhead may exceed the work itself. Measure total time to usable result as well as main-thread responsiveness. Pooling workers can save startup cost for repeated jobs, yet a pool adds queueing and cancellation rules. Keep one worker until measurement justifies a more complex arrangement.
Failure trace
The route reuses one worker but has no job identity. A slow case 47 summary arrives after case 62 and replaces the panel. The team adds an ID check but leaves the transferred caseBytes in a local cache; another action reads the detached buffer and fails. Use current-job checks and an explicit ownership rule for bytes. On route exit, clear handlers or terminate the worker. Test errors and very large files; a valid message envelope does not guarantee the parser can handle unbounded input.
Verification
- An obsolete worker result cannot update a newer case route.
- Transferred input is not reused from the sender after ownership moves.
- Malformed input and route exit release worker resources and show a controlled state.
Practice drill
Parse the same measurement file on the main thread and in a worker. Record input responsiveness, transfer time, parse time, and peak memory. Start a job for case 47, switch to 62, and confirm no old summary appears. Inspect the sender's buffer after transfer to understand ownership. Trigger a malformed file and confirm the worker returns a bounded error state. Finally leave the route mid-job and verify the worker and message listener are cleaned up.
Decision note
Use a worker when measured computation blocks interaction enough to justify startup and messaging cost; make job identity and data ownership explicit.
Common Mistakes
- Assuming a worker can directly update DOM controls.
- Posting a cancel message to a worker that never yields and expecting immediate interruption.
- Reusing a transferred buffer after detachment.
Connected lessons
Browser Execution and Resource Lifecycle; Event Loop Tasks, Microtasks, and Paint; Cooperative Main-Thread Scheduling; Browser Memory and Resource Lifecycles; React Effects and Request Races; TypeScript and Runtime API Boundaries; Browser Memory and Resource Lifecycles.
Apply and check
Build Project: responsive import worker and review Web Development: layout and runtime contracts quiz.
