Web Workers

2022-12-12

Recently I have been working on an application which requires a lot of processing over some data in the browser. Processing that can take up to 10-15 seconds to complete.

This provided a problem, as if we did this processing directly in our SPA it would occupy the UI thread for 10-15 seconds and would result in the UI being unresponsive.

This is the perfect use case for Web Workers. Web Workers allow you to run some JavaScript on a background thread, and you can communicate to and from this worker to allow you to offload resource intensive tasks e.g. I/O, data processing, computation.

Browser Support

There is really great browser support for Web Workers (all the way back to IE10!) so you should be able to use them worry free. https://caniuse.com/webworkers

How to use

So you will need your UI code:

var worker = new Worker('/src/worker.js');

worker.postMessage([100, 200, 300, 400, 500]);

worker.onmessage = (e) => {
    document.getElementById('app').innerHTML = e.data.join('<br />');
};

and your worker's JS file:

onmessage = (e) => {
    const outputArray = processData(e.data);
    postMessage(outputArray);
};

function processData(data) {
    return data.map((x) => x * 1.5);
}

In our UI code we initialise a new instance of the Worker class, this accepts a path to your worker's JS file. Keep in mind that this path is to the compiled output location of that file so may not always be the same as its path relative to your UI file.

Once created we can interact with the worker in 2 ways:

Post Message

Firstly we can call postMessage this allows us to send a data payload to the worker, this can be any object, so you could send a particular message with some structure or just an array of data, the possibilities are open to your implementation.

This data will then be copied to the background thread and passed into the onmessage function in your worker, where you can do any processing you may want.

Keep in mind that any data passed into the onmessage will be copied to the background thread, so if you have large objects as arguments it will take some time to copy them over. If you do run into this you may be able to use transferables to share the memory so no copy is made.

On Message

This is a callback we assign to the worker that will be invoked any time the worker posts back a message to your UI thread. This is where you will want to deal with any result of the background work that your worker has been running.

In the Worker

In the worker we also have the same to methods available and it works in much the same way, we can listen for messages by assigning a callback the the onmessage property and we can post back our results with the postMessage function.

Final thoughts

Web Workers are great for offloading intensive computation / long running tasks to a background thread and we can interact with this use a messaging like API. You should use them when wanting to maintain UI interactivity / thread work whilst also needing to do some other kind of background work.

Also note there is some alternatives to Web Workers that may fit your use case such as a Service Worker and Shared Worker.

Here's the code: https://codesandbox.io/s/web-worker-heynkk