Quiz

What are workers in JavaScript used for?

Topics
JavaScript
Edit on GitHub

TL;DR

Workers in JavaScript are background threads that allow you to run scripts in parallel with the main execution thread, without blocking or interfering with the user interface. Their key features include:

  • Parallel processing: Workers run in a separate thread from the main thread, allowing your web page to remain responsive to user interactions while the worker performs its tasks. It's useful for moving CPU-intensive work off the main thread and be free from JavaScript's single-threaded nature.
  • Communication: Uses postMessage() and onmessage/ 'message' event for messaging.
  • Access to web APIs: Workers have access to various Web APIs, including fetch(), IndexedDB, and Web Storage, allowing them to perform tasks like data fetching and persisting data independently.
  • No DOM access: Workers cannot directly manipulate the DOM, thus cannot interact with the UI, ensuring they don't accidentally interfere with the main thread's operation.

There are three main types of workers in JavaScript:

  • Web workers / Dedicated workers
    • Run scripts in background threads, separate from the main UI thread.
    • Useful for CPU-intensive tasks like data processing, calculations, etc.
    • Cannot directly access or manipulate the DOM.
  • Service workers
    • Act as network proxies, handling requests between the app and network.
    • Enable offline functionality, caching, and push notifications.
    • Runs independently of the web page, even when it's closed.
  • Shared workers
    • Can be shared by multiple scripts running in different windows or frames, as long as they're in the same domain.
    • Scripts communicate with the shared worker by sending and receiving messages.
    • Useful for coordinating tasks across different parts of a web page.

Workers in JavaScript

Workers in JavaScript are a way to run scripts in background threads, separate from the main execution thread of a web page. This allows for long-running or computationally intensive tasks to be offloaded from the main thread, preventing the user interface from becoming unresponsive or janky.

Web workers / Dedicated workers

  • Run scripts in background threads separate from the main UI thread.
  • Designed for CPU-intensive tasks like data processing, mathematical computations, etc. Generally the non-async work.
  • Cannot directly access the DOM or other main thread resources for security.
  • Communicates with main thread via asynchronous message passing – postMessage() and onmessage/ 'message'.
  • Terminated when main script is unloaded or explicitly terminated.

Web workers can be used for:

  • Image/video processing
  • Data compression
  • Complex math

Creating a web worker

To create a web worker, you need a separate JavaScript file that contains the code for the worker. Here's an example:

main.js (main script)

// Check if the browser supports workers
if (window.Worker) {
// Create a new Worker
const myWorker = new Worker('worker.js');
// Post a message to the worker
myWorker.postMessage('Hello, Worker!');
// Listen for messages from the worker
myWorker.onmessage = function (event) {
console.log('Message from Worker:', event.data);
};
// Error handling
myWorker.onerror = function (error) {
console.error('Error from Worker:', error);
};
}

worker.js (worker script)

// Listen for messages from the main script
onmessage = function (event) {
console.log('Message from Main Script:', event.data);
// Perform a task (e.g., some computation)
const result = event.data + ' - Processed by Worker';
// Post the result back to the main script
postMessage(result);
};

In this example:

  • main.js creates a worker using the Worker constructor and specifies worker.js as the script to run in the worker thread.
  • It posts a message to the worker using postMessage().
  • The worker script (worker.js) listens for messages from the main script using onmessage.
  • After processing the message, the worker posts a message back to the main script using postMessage().
  • The main script listens for messages from the worker using onmessage on the Worker instance.

Service workers

  • Act as a network proxy between web app, browser, and network.
  • Can intercept and handle network requests, cache resources.
  • Enable offline functionality and push notifications.
  • Have a lifecycle managed by the browser (install, activate, update).
  • No access to DOM and main thread resources for security.

Service workers can be used for:

  • Caching
  • Offline support
  • Request handling
  • Background sync

Creating a service worker

main.js (main script)

if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('/service-worker.js')
.then(function (registration) {
console.log('Service Worker registered:', registration);
})
.catch(function (err) {
console.log('Service Worker registration failed:', err);
});
}

service-worker.js (service worker script)

self.addEventListener('fetch', function (event) {
event.respondWith(
caches.match(event.request).then(function (response) {
// return cached response if available
if (response) {
return response;
}
// Otherwise, fetch from network
return fetch(event.request);
}),
);
});

In this example:

  • The main script registers a service worker at /service-worker.js.
  • The service worker listens for the fetch() event, which is fired whenever the browser makes a network request.
  • The service worker first checks if the requested resource is cached using caches.match(event.request).
  • If it is, it returns the cached response. Otherwise, it fetches the resource from the network using fetch(event.request).

Shared workers

  • Can be accessed from multiple scripts in different windows/tabs/iframes.
  • Allow data sharing between browser contexts via a messaging interface.
  • Similar to dedicated web workers but with a broader scope.

Use cases for shared workers:

  • State sharing across multiple windows.

Bonus: Worklets

The Worklet interface is a lightweight version of Web Workers and gives developers access to low-level parts of the rendering pipeline. With Worklets, you can run JavaScript and WebAssembly code to do graphics rendering or audio processing where high performance is required.

You are not expected to know about worklets, so it won't be covered in great detail. Read more about worklets on MDN.

Considerations and limitations

  • Same-Origin policy: Workers must comply with the same-origin policy, meaning the script that creates the worker and the worker script itself must be from the same origin.
  • No DOM access: Workers do not have direct access to the DOM. They can communicate with the main thread through messages.
  • Performance: Creating and managing workers incurs overhead. They should be used judiciously for tasks that truly benefit from parallel execution.
  • Error handling: Proper error handling mechanisms should be in place to handle any issues within the worker scripts.

Further reading

Edit on GitHub