Stop Writing postMessage Manually For Workers — I Built a Decorator for That
Tags: angular, react, webdev, javascript
Web Workers are one of the most underused features in modern web development. They let you run heavy JavaScript off the main thread — keeping your UI smooth and responsive.
But the API is painful:
// Standard Worker code — just to call ONE function
const worker = new Worker('./my.worker.js');
const requestId = Math.random();
worker.postMessage({ id: requestId, command: 'processData', payload: data });
worker.onmessage = (event) => {
if (event.data.id === requestId) {
console.log(event.data.result);
}
};
You need request IDs, response matching, manual routing, port management for SharedWorkers... for every single method call.
So I built ngx-worker-bridge to eliminate all of that.
What it looks like instead
Define your background logic (runs in the worker thread):
import { setState } from 'ngx-worker-bridge';
export class DataModule {
private count = 0;
increment() {
this.count++;
setState('counter', this.count); // broadcasts to ALL tabs
}
async processData(payload: any) {
// heavy work here — UI thread never blocks
return expensiveOperation(payload);
}
}
Call it from Angular like a normal service:
import { Injectable } from '@angular/core';
import { RunInWorker, workerStore } from 'ngx-worker-bridge';
@Injectable({ providedIn: 'root' })
export class DataService {
count$ = workerStore<number>('counter', 'shared'); // reactive, auto-updates
@RunInWorker({ bridge: 'shared', namespace: 'data' })
increment(): Promise<void> { return null as any; }
@RunInWorker({ namespace: 'data' })
processData(payload: any): Promise<any> { return null as any; }
}
Or from React with a hook:
import { useWorkerStore } from 'ngx-worker-bridge/react';
function App() {
const count = useWorkerStore<number>('counter', 'shared');
return <button onClick={() => service.increment()}>Count: {count}</button>;
}
No postMessage. No onmessage. No request ID tracking. Just a decorator and a hook.
The SharedWorker feature
The real power comes from SharedWorker support. A SharedWorker runs once and is shared across all open browser tabs. When you call setState('counter', value) inside your module, it broadcasts to every connected tab instantly.
Open 5 tabs — they all stay in sync. Without a server. Without WebSockets.
This is useful for:
- Notification counts
- Live stock/crypto prices
- Shared timers or sessions
- One WebSocket connection shared across all tabs
Install
# Angular (RxJS already included)
npm i ngx-worker-bridge
# React
npm i ngx-worker-bridge rxjs
- GitHub: github.com/yashwantyashu/worker-bridge
- npm: npmjs.com/package/ngx-worker-bridge
- Demo: github.com/yashwantyashu/worker-demo-app
Would love feedback — especially from anyone who's dealt with SharedWorker pain before.
Top comments (0)