AngularJS和网络工作者

arg*_*g20 72 javascript web-worker angularjs

angularJS如何使用Web worker在后台运行进程?这样做我应该遵循什么模式?

目前,我正在使用一个在单独的Web worker中具有该模型的服务.此服务实现以下方法:

ClientsFacade.calculateDebt(client1); //Just an example..
Run Code Online (Sandbox Code Playgroud)

在实现中,此方法使用数据向worker发送消息.这允许我抽象它在一个单独的线程中执行的事实,我还可以提供一个查询服务器的实现,甚至是在同一个线程中执行此操作的实现.

由于我是javascript的新手,而且我只是从其他平台上回收知识,我想知道这是你要做的事情,还是我正在使用的Angular,提供了一种方法.这也引入了我的架构的变化,因为工作人员必须明确地将更改推送到控制器,然后控制器更新其值,然后这反映在视图中,我是否过度设计了这个?有点令人沮丧的是,网络工作者通过不允许我共享内存等来"保护"我.

gan*_*raj 97

与Web worker的通信通过消息传递机制实现.拦截这些消息发生在回叫中.在AngularJS中,正如您所注意到的那样,放置Web工​​作者的最佳位置是在服务中.解决这个问题的最好方法是使用Promular,Angular可以使用它.

这是a webworker中的一个例子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;
        }
    };

});
Run Code Online (Sandbox Code Playgroud)

现在,无论访问Hello World服务的外部实体是什么,都不需要关心实现细节HelloWorldService- HelloWorldService可能会通过a web worker,over http或者处理数据来处理数据.

希望这是有道理的.

  • 如果在工人完成之前再次调用`doWork`,是否会被"推迟"覆盖?然后第二个承诺将以第一个结果解决,第一个承诺永远不会解决. (9认同)
  • 什么是**doWork.js****var worker = new Worker('doWork.js');**? (5认同)
  • 是的,是否有可能在doWork.js中使用$ http这样的服务? (3认同)
  • 它是对包含web-worker代码的外部js文件的引用. (2认同)

小智 16

一个非常有趣的问题!我发现web worker规范有点尴尬(可能有充分的理由,但仍然很尴尬).将工作程序代码保存在单独的文件中的需要使得服务的意图难以阅读,并且在角度应用程序代码中引入了对静态文件URL的依赖性.使用URL.createObjectUrl()可以缓解此问题,该URL可用于为JavaScript字符串创建URL.这允许我们在创建worker的同一文件中指定worker代码.

var blobURL = URL.createObjectURL(new Blob([
    "var i = 0;//web worker body"
], { type: 'application/javascript' }));
var worker = new Worker(blobURL);
Run Code Online (Sandbox Code Playgroud)

Web worker规范还使工作者和主线程上下文完全分开,以防止出现死锁和活锁等情况.但这也意味着如果没有一些摆弄,你将无法在工人中获得角度服务.在浏览器中执行JavaScript时,工作人员缺少我们(和角度)期望的一些东西,比如全局变量"document"等.通过"模拟"工作者中所需的这些浏览器功能,我们可以获得角度运行.

var window = self;
self.history = {};
var document = {
    readyState: 'complete',
    cookie: '',
    querySelector: function () {},
    createElement: function () {
        return {
            pathname: '',
            setAttribute: function () {}
        };
    }
};
Run Code Online (Sandbox Code Playgroud)

一些功能显然不起作用,绑定到DOM等.但注入框架和例如$ http服务将工作得很好,这可能是我们想要的工人.我们得到的是我们可以在工人中运行标准角度服务.因此,我们可以像对待任何其他角度依赖一样对工作中使用的服务进行单元测试.

我做这阐述详细了解一下这个帖子在这里创造它创建一个实现了思想上面所讨论的服务的GitHub库在这里


Oct*_*ane 11

我发现网络工作者的全面工作示例的角位置

webworker.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;
    });

}]);
Run Code Online (Sandbox Code Playgroud)

它使用promises等待worker返回结果.

  • 托管该示例的网站已不再可用.这是存档链接https://web.archive.org/web/20150709233911/http://www.codingterminal.com/articles/092014/1/XMLHttpRequest%20using%20AngularJS%20Promises%20and%20HTML5%20Web%20Workers. PHP (3认同)

Cha*_*dla 7

角度Web工作者与投票示例

当您与AngularJS中的工作人员打交道时,通常要求您的工作脚本是内联的(如果您正在使用一些构建工具,如gulp/grunt),我们可以使用以下方法实现此目的.

下面的示例还说明了如何使用worker对服务器进行轮询:

首先让我们创建我们的工厂:

    module.factory("myWorker", function($q) {
    var worker = undefined;
    return {
        startWork: function(postData) {
            var defer = $q.defer();
            if (worker) {
                worker.terminate();
            }

            // function to be your worker
            function workerFunction() {
                var self = this;
                self.onmessage = function(event) {
                    var timeoutPromise = undefined;
                    var dataUrl = event.data.dataUrl;
                    var pollingInterval = event.data.pollingInterval;
                    if (dataUrl) {
                        if (timeoutPromise) {
                            setTimeout.cancel(timeoutPromise); // cancelling previous promises
                        }

                        console.log('Notifications - Data URL: ' + dataUrl);
                        //get Notification count
                        var delay = 5000; // poller 5sec delay
                        (function pollerFunc() {
                            timeoutPromise = setTimeout(function() {
                                var xmlhttp = new XMLHttpRequest();
                                xmlhttp.onreadystatechange = function() {
                                    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                                        var response = JSON.parse(xmlhttp.responseText);
                                        self.postMessage(response.id);
                                        pollerFunc();
                                    }
                                };
                                xmlhttp.open('GET', dataUrl, true);
                                xmlhttp.send();
                            }, delay);
                        })();
                    }
                }
            }
            // end worker function

            var dataObj = '(' + workerFunction + ')();'; // here is the trick to convert the above fucntion to string
            var blob = new Blob([dataObj.replace('"use strict";', '')]); // firefox adds user strict to any function which was blocking might block worker execution so knock it off

            var blobURL = (window.URL ? URL : webkitURL).createObjectURL(blob, {
                type: 'application/javascript; charset=utf-8'
            });

            worker = new Worker(blobURL);
            worker.onmessage = function(e) {
                console.log('Worker said: ', e.data);
                defer.notify(e.data);
            };
            worker.postMessage(postData); // Send data to our worker.
            return defer.promise;
        },
        stopWork: function() {
            if (worker) {
                worker.terminate();
            }
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

接下来从我们的控制器调用工厂工厂:

var inputToWorker = {
    dataUrl: "http://jsonplaceholder.typicode.com/posts/1", // url to poll
    pollingInterval: 5 // interval
};

myWorker.startWork(inputToWorker).then(function(response) {
    // complete
}, function(error) {
    // error
}, function(response) {
    // notify (here you receive intermittent responses from worker)
    console.log("Notification worker RESPONSE: " + response);
});
Run Code Online (Sandbox Code Playgroud)

您可以随时致电myWorker.stopWork();控制器终止工作人员!

这是在IE11 +和FF以及Chrome中测试的