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