Using Web Workers in Angular for Performance Optimization

In modern web applications, performance is critical, especially when handling complex, data-intensive operations. One often-overlooked strategy to maintain UI responsiveness is leveraging Web Workers.

In this article, I’ll walk you through how to implement a Web Worker in Angular, enable communication between the main thread and the worker, and extend it to handle multiple types of tasks from within a single worker—keeping your UI buttery smooth even during heavy computations.


🚀 Why Web Workers?

Web Workers allow you to run computationally heavy tasks off the main thread, so that animations, transitions, and interactions aren’t blocked. This is particularly useful for applications processing large datasets, rendering complex visuals, or performing real-time calculations.


🛠️ Setting Up a Web Worker in Angular

Angular CLI makes it incredibly easy to add a worker:

ng generate web-worker app

This command creates a worker file (app.worker.ts) and adds the boilerplate for two-way communication.

Scaffolded Code Example

app.worker.ts:

addEventListener('message', ({ data }) => {
const response = `worker response to ${data}`;
postMessage(response);
});

app.component.ts:

if (typeof Worker !== 'undefined') {
const worker = new Worker(new URL('./app.worker', import.meta.url));
worker.onmessage = ({ data }) => {
console.log(`page got message: ${data}`);
};
worker.postMessage('hello');
} else {
// Fallback if Web Workers aren't supported
}

🧩 Handling Multiple Tasks with One Worker

Let’s say we have an Angular app dealing with proposal items, and we want to offload two tasks to a Web Worker:

  1. Extracting parts from a list of proposal items
  2. Setting the number of selected room items

✅ Worker Code: proposal-item.worker.ts

/// <reference lib="webworker" />

import { AreaItemTypeEnum } from '@app/core/enums';
import { IProposalAreaItemModel, IProposalAreaPartModel } from '@app/core/models/proposal.models';

addEventListener('message', ({ data }) => {
const { eventType, dataToSend } = data;

switch (eventType) {
case 'getParts':
postMessage(getParts(dataToSend));
break;

case 'setNumRoomItemsSelected':
postMessage(dataToSend); // Example placeholder
break;

default:
postMessage('Unknown event type');
}
});

function getParts(itemsArray: Array<IProposalAreaItemModel>): IProposalAreaPartModel[] {
return itemsArray?.filter(item => item?.type === AreaItemTypeEnum.Part) as IProposalAreaPartModel[];
}

🎯 Component Integration: Generalized Web Worker Method

We define a reusable method to initialize and communicate with the Web Worker:

private InitializeWebWorker(eventType: string, dataToSend: any): Promise<any> {
return new Promise((resolve, reject) => {
if (typeof Worker !== 'undefined') {
const worker = new Worker(new URL('./proposal-item.worker', import.meta.url));
worker.postMessage({ eventType, dataToSend });

worker.onmessage = ({ data }) => resolve(data);
worker.onerror = (error) => reject(error);
} else {
reject('Web Workers are not supported in this environment.');
}
});
}

📦 Example Methods Using the Worker

async setNumRoomItemsSelected(value: number): Promise<void> {
this.numRoomItemsSelected = await this.InitializeWebWorker('setNumRoomItemsSelected', value);
}

getParts(itemsArray: IProposalAreaItemModel[]): Promise<IProposalAreaPartModel[]> {
return this.InitializeWebWorker('getParts', itemsArray);
}

These methods offload their logic to the worker and receive the result asynchronously.


🌟 Benefits of Using Web Workers in Angular

  • ⚡ Improved Performance
    Keeps the UI thread responsive during heavy processing
  • 📈 Scalability
    Efficient for complex operations like filtering, parsing, or crunching large datasets
  • ♻️ Reusability
    Modular and extensible for multiple use cases across the app

🧠 Final Thoughts

Integrating Web Workers into an Angular application doesn’t just improve performance—it’s a smart architectural decision for apps that handle a lot of data or real-time updates. With the pattern outlined here, you can easily extend a single worker to support multiple task types, making your code cleaner and more maintainable.

If you’re working on performance-critical features or just want to keep your UI consistently snappy, it’s time to bring Web Workers into your Angular toolkit.

Leave a Comment

Your email address will not be published. Required fields are marked *