WebWorker Communication using RxJS and Angular

Suresh Nagar
3 min readAug 26, 2019

I have an Angular application which uses d3-force layout to calculate and render a large graph. As it is a long running computation intensive task I wanted to move it to web worker to keep the application responsive and also report progress while the layout is being calculated.

Photo by Pavan Trikutam on Unsplash

With Angular8 it is easy to create a web worker and move the computation intensive task to web worker but communication with web worker is not very straightforward. You can use libraries like comlink to expose an ES6 class from a worker and use it as a normal class in your application. But comlink comes with two main issues. First, you need proxy-polyfill to make it work in older browser and secondly, it exposes everything as promise and not as observable.

So I decided to write our own communication mechanism which exposes a worker as observable to run a long running d3-force in web worker and also to report progress on each tick.

Sending message to web worker.

I was looking for a consumption model as below, where any message sent to web worker would return back an Observable.

Wrap worker and sendMessage

I started with creating a class RxifyWorker to wrap the Worker and expose functions like sendMessage which wraps the user payload into a message structure, adds an identifier and posts a message on worker. It also creates a subject, registers the subject against the message Id and returns to caller.

The class also registers a listener on Worker to receive messages sent by web worker and relay them on the subject returned earlier by sendMessage.

Exposing web worker

We also need to receive messages in web worker and return an observable where we send the calculation progress or the final calculated layout when complete.

Expose web worker and handle messages.

To implement this, I started by creating RegisterWorker which registers a message handler. The handler function will receive the user payload posted by application and returns an observable. This makes it possible for the worker to return multiple responses against a single message sent by application e.g. in our case on every tick in layout calculation, we send layout calculated percentage to application.

register-worker.ts

Finally in the worker, I calculate the static force layout and report back the percentage completed on each tick.

Thats it! after this the application was responsive while the layout is being calculated and I could also report the calculated percentage.

Check out source at https://github.com/nagarsuresh/rxify-worker-angular and Demo at https://nagarsuresh.github.io/rxify-worker-angular/rxify-worker-angular/

--

--