Communication between Web Worker and the main thread is primarily achieved through the postMessage() method and onmessage event.
Basic Communication Mechanism
Main Thread Sending Messages to Worker
javascriptconst worker = new Worker('worker.js'); // Send simple data worker.postMessage('Hello Worker'); // Send complex objects worker.postMessage({ type: 'compute', data: [1, 2, 3, 4, 5] }); // Send Transferable Objects const buffer = new ArrayBuffer(1024); worker.postMessage({ buffer }, [buffer]);
Worker Sending Messages to Main Thread
javascript// worker.js self.onmessage = function(event) { const result = processData(event.data); self.postMessage(result); }; // Or use addEventListener self.addEventListener('message', function(event) { self.postMessage({ status: 'received' }); });
Message Passing Characteristics
1. Deep Copy vs Transfer
By default, messages are passed through deep copy:
javascript// Deep copy - original data retained const data = { value: 42 }; worker.postMessage(data); console.log(data.value); // 42 - data still exists
Use Transferable Objects for transfer:
javascript// Transfer - original data cleared const buffer = new ArrayBuffer(1024); worker.postMessage({ buffer }, [buffer]); console.log(buffer.byteLength); // 0 - data has been transferred
2. Structured Clone Algorithm
postMessage uses the structured clone algorithm, supporting:
- Basic types (string, number, boolean, null, undefined)
- Objects and arrays
- Date, RegExp, Blob, File, ArrayBuffer
- Map, Set, ImageData
Does not support:
- Functions
- DOM nodes
- Error objects
- Symbol
Bidirectional Communication Example
javascript// Main thread const worker = new Worker('worker.js'); worker.onmessage = function(event) { console.log('Worker says:', event.data); }; worker.postMessage({ action: 'start' }); // worker.js self.onmessage = function(event) { if (event.data.action === 'start') { // Execute task const result = heavyComputation(); self.postMessage({ action: 'complete', result }); } };
Message Queue
Messages are asynchronous and passed through a message queue:
javascript// Main thread sends multiple messages consecutively for (let i = 0; i < 5; i++) { worker.postMessage({ index: i }); } // Worker receives in order self.onmessage = function(event) { console.log('Processing:', event.data.index); };
Error Handling
javascript// Main thread listens for Worker errors worker.onerror = function(event) { console.error('Worker error:', event.message); console.error('Filename:', event.filename); console.error('Line:', event.lineno); }; // Internal error handling in Worker try { // Code that might error } catch (error) { self.postMessage({ error: error.message }); }
Performance Optimization Recommendations
- Use Transferable Objects: For large data (ArrayBuffer, Blob), use transfer instead of copy
- Batch Processing: Reduce message passing frequency, merge data
- Avoid Frequent Communication: Try to complete more calculations within the Worker
- Use SharedArrayBuffer: Multiple Workers share memory (requires specific header configuration)