Using HTML5 Web Workers with AngularJs

Web workers introduced in Html5 provide a background mechanism to perform multi-threaded tasks. They add the ability to perform computationally heavy tasks like downloading or mathematical computation without hanging the user interface. Although AngularJS and web workers are both intended for asynchronous execution, both serve different purposes and should be used in conjunction.

Angular JS Promises

Deferred and promises set a reference to a result yet not available. Once resolve is called the result becomes available and the appropriate action is taken based on the result in the .then section.

Web Workers

Web workers on the other hand are used to perform actual work asynchronously. They are relatively light weight as they use operating system threads and hence are better suitable for computationally heavy, long running or periodic tasks.

Getting Started

First we set up the index.html page where testworker is the state used in the state provider. Clicking on Start Web Worker will load the template associated with the testworker into the ui-view.

// index.html<!doctype html><html ng-app="webworker"><head>    <title> Web Worker </title></head><body>    <script src="angular.js"></script>    <script src="angular-router-ui.min.js"></script>    <script src="routing.js"></script>    <script src="webWorkerCtrl.js"></script>    <a ui-sref="testworker">Start Web Worker</a>    <div ui-view></div></body></html>

Set up the application routing.

// routing.jsvar webworker = angular.module('webworker', ['ui.router']).config(function ($stateProvider, $urlRouterProvider) {                            $urlRouterProvider.otherwise("/index.html");                            $stateProvider    .state('testworker', {        url: "/testworker",        templateUrl: "webworker.html",        controller: "webWorkerCtrl"    });});

Set up the data binding.

// webworker.htmlLoading...{{workerReplyUI}}

Next we write the controller which makes the call to the external web worker file. The callWebWorker function spawns the new web worker, posts the url to download from and returns a promise object. Now the .then call will wait until the promise is resolved which happens in the onmessage callback. Once the web worker posts back the result, onmessage function is called. Inside the onmessage function, the resolve sends the data back to the calling function. On receiving the data the .then executes and the controller sets the result to the data binded workerReplyUI.

// webWorkerCtrl.jswebworker.controller('webWorkerCtrl', ['$scope', '$q', function ($scope, $q) {$scope.workerReplyUI;$scope.callWebWorker = function () {var worker = new Worker('worker.js');var defer = $q.defer();worker.onmessage = function(e) {defer.resolve(e.data);worker.terminate();};worker.postMessage("http://jsonplaceholder.typicode.com/users");return defer.promise;}$scope.callWebWorker().then(function (workerReply) {$scope.workerReplyUI = workerReply;});}]);

The webworker recieves the postmessage from the controller in the onmessage function. It initializes an HttpClient object to send a GET request to the server. When the GET request completes, the web worker posts the result back to the calling controller.

// worker.jsthis.onmessage = function (url) {getDataFromURL(url.data);}var HttpClient = function () {this.get = function (Url, Callback) {HttpRequest = new XMLHttpRequest();HttpRequest.onreadystatechange = function () {if (HttpRequest.readyState == 4 && HttpRequest.status == 200) {console.log(HttpRequest.responseText.length);Callback(HttpRequest.responseText);}}HttpRequest.open("GET", Url, true);HttpRequest.send(null);}}function getDataFromURL(url) {Client = new HttpClient();Client.get(url, function (answer) {postMessage(answer);});}

Comments

Popular posts from this blog

MATLAB code for Circular Convolution using Matrix method

Positive number pipe in angular 2+