Web Workers in React

MentorAide
3 min readJun 6, 2024

--

Photo by Ümit Yıldırım on Unsplash

Introduction

In a recent project, we made a tree view representation using a large hierarchical dataset from an external source. All was good until we wanted to add a special filter to it. We thought, “Let’s do the filtering right in the browser since the data is already here on our website.” However, applying the filter made the browser completely unresponsive for a few seconds. So, we started looking for a better way to do this and stumbled upon web workers. In this article, we’ll explore what web workers are, and how to integrate them seamlessly in a React application.

What are Web Workers?

Web workers are JavaScript scripts that run in a separate thread from the main thread of the browser. This means that they can run independently of the main thread, without blocking it. This can be useful for tasks that are CPU-intensive or that take a long time to complete.

How do Web Workers work?

Web workers use a messaging system to communicate with the main thread. The main thread can send messages to the worker to request that it perform a task. The worker can then send messages back to the main thread to report the results of the task.

How to use Web Workers in React

Follow the below steps to integrate web workers in your React applications:

Setup WorkerFactory
We’ll start by creating the WorkerFactory, which separates web worker scripts from the main bundle to prevent bunding issues. We’ll create a file named WorkerFactory.jsx within the src directory:

// src/WorkerFactory.jsx
export default class WorkerFactory {
constructor(workerFunction) {
const workerCode = workerFunction.toString();
const workerBlob = new Blob([`(${workerCode})()`]);
return new Worker(URL.createObjectURL(workerBlob));
}
}

Write Web Worker Script:
Now, we’ll create a file called myWorker.worker.js in the workers folder within the src directory (place other worker scripts here). This script defines the tasks our web worker will perform:

// src/workers/myWorker.worker.js
export default () => {
self.addEventListener('message', (event) => {
const data = event.data;
const result = performIntensiveTask(data);
self.postMessage(result);
});
function performIntensiveTask(data) {
// ... perform calculations or processing ... return result;
}
};

Initialize the Worker:
In the React code, we’ll initialize the WorkerFactory to create a web worker instance:

import WorkerFactory from '../WorkerFactory';
import myWorker from '../workers/myWorker.worker';
const workerInstance = new WorkerFactory(myWorker);

Using in Redux Action:

Finally, we’ll use the workerInstance in a Redux action (or anywhere else in our app) to perform tasks asynchronously:

export function myAction(data) {
return (dispatch) => {
dispatch(showLoader()); // Show loading symbol
// Send data to the worker
workerInstance.postMessage(data); // Listen for messages from the worker
workerInstance.onmessage = (res) => {
dispatch({
type: RECEIVE_DATA,
results: res.data,
});
dispatch(hideLoader()); // Hide loading symbol
}; // Handle errors from the worker
workerInstance.onerror = (err) => {
dispatch(hideLoader()); // Hide loading symbol
// Use 'err' to show an error message
};
};
}

When the Redux action is called, it uses the postMessage method on workerInstance. This sets off the onmessage event inside the myWorker script. The worker then does its job and, when it’s done, it uses postMessage to let the Redux action know. This triggers the onmessage part in your Redux action, bringing back the results of the worker’s work.

Benefits

Enhanced Performance: Offloading resource-intensive tasks to web workers prevents the main thread from getting blocked, leading to a more responsive UI.

Parallel Processing: Web Workers process tasks concurrently, optimizing performance on multi-core processors.

Limitations

No Direct DOM Access: Web workers cannot directly access the DOM, limiting their use to calculations and data processing.

Cross-Origin Restrictions: Web workers are subject to cross-origin restrictions. Shared Workers can be used to overcome this limitation within the same origin.

--

--

MentorAide
MentorAide

No responses yet