AngularJS and web workers

arg20 picture arg20 · May 23, 2013 · Viewed 47.6k times · Source

How can angularJS use web workers to run processes in the background? Is there any pattern I should follow on doing this?

Currently, I am using a service that has the model in a separate web worker. This service implements methods like:

ClientsFacade.calculateDebt(client1); //Just an example..

In the implementation, this method sends a message to the worker with the data. This allows me to abstract the fact that it is being performed in a separate thread and I could also provide an implementation that queries against a server or even one that does this action in the same thread.

Since I'm new to javascript and I'm just recycling knowledge I have from other platforms I wonder if this is something you would do or perhaps Angular which is what I am using, offers a sort of way of doing this. Also this introduces a change in my architecture since the worker must explicitly push changes to the controller, which then updates its values and then this is reflected in the view, am I over engineering this? It's a bit frustrating that web workers "protect" me so much from screwing up by not allowing me to share memory etc.

Answer

ganaraj picture ganaraj · May 24, 2013

Communication with Web workers happens through a messaging mechanism. Intercepting these messages happens in a call back. In AngularJS, the best location to put a web worker is in a service as you duly noted. The best way to deal with this is to use promises, which Angular works amazingly with.

Here is an example of a webworker in a service

var app = angular.module("myApp",[]);

app.factory("HelloWorldService",['$q',function($q){

    var worker = new Worker('doWork.js');
    var defer = $q.defer();
    worker.addEventListener('message', function(e) {
      console.log('Worker said: ', e.data);
      defer.resolve(e.data);
    }, false);

    return {
        doWork : function(myData){
            defer = $q.defer();
            worker.postMessage(myData); // Send data to our worker. 
            return defer.promise;
        }
    };

});

Now whatever external entity that accesses Hello World service need not care about the implementation details of HelloWorldService - HelloWorldService could probably process the data over a web worker, over http or do the processing right there.

Hope this makes sense.