Web Workers run JavaScript in a separate thread, parallel to the main thread. They cannot access the DOM but can perform CPU-intensive work without blocking UI.

Creating a Worker

main.js

  const worker = new Worker('worker.js');

worker.postMessage({ numbers: [1, 2, 3, 4, 5] });

worker.onmessage = (e) => {
    console.log('Result:', e.data); // Result: 15
};

worker.onerror = (e) => {
    console.error('Worker error:', e.message);
};

// Terminate when done
// worker.terminate();
  

worker.js

  self.onmessage = (e) => {
    const sum = e.data.numbers.reduce((a, b) => a + b, 0);
    self.postMessage(sum);
};
  

Inline Worker with Blob

  const code = `
    self.onmessage = (e) => {
        self.postMessage(e.data * 2);
    };
`;
const blob = new Blob([code], { type: 'application/javascript' });
const worker = new Worker(URL.createObjectURL(blob));
worker.postMessage(21);
worker.onmessage = (e) => console.log(e.data); // 42
  

Transferable Objects

Transfer ownership of ArrayBuffer for zero-copy performance:

  const buffer = new ArrayBuffer(1024 * 1024);
worker.postMessage(buffer, [buffer]);
// buffer is now unusable in main thread
  

SharedWorker

Shared across multiple tabs/windows:

  const worker = new SharedWorker('shared-worker.js');
worker.port.start();
worker.port.postMessage('hello');
worker.port.onmessage = (e) => console.log(e.data);
  

Service Workers

Special workers for offline caching and push notifications (Progressive Web Apps):

  // Register in main thread
if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/sw.js')
        .then(reg => console.log('SW registered', reg))
        .catch(err => console.error('SW failed', err));
}
  

Use Cases

Task Why use Worker
Image processing Heavy pixel manipulation
Large data parsing JSON/CSV of megabytes
Cryptography CPU-intensive hashing
Scientific simulation Long computations
Real-time analytics Aggregate without blocking UI

Limitations

  • No DOM access (document, window)
  • No direct access to parent variables (communicate via messages)
  • Same-origin policy applies to worker script URL
  • Workers have startup overhead — not for trivial tasks

Module Workers (Modern)

  const worker = new Worker('worker.js', { type: 'module' });
// worker.js can use import/export
  

Use Web Workers when main-thread work would cause visible lag or block user interaction.