Webworker回调后返回结果 [英] Webworker return result after callback

查看:76
本文介绍了Webworker回调后返回结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Angular服务,其中与Webworkers结合使用 $ q 服务.在使用Webworkers之前的原始函数中,我的 completeClass 函数将返回一个对象.

I have an Angular service where I'm using $q service in combination with webworkers. In my original function before using webworkers, my completeClass function would return an object.

我替换了代码,以将消息发布到新的Web Worker脚本中.Webworker的回调位于我的 initWorkers 函数中,在其中添加了eventlistener.

I replaced the code to post a message to my new web worker script. The callback of the webworker is in my initWorkers function where I add the eventlistener.

我的目标是 completeClass 函数返回Webworker的结果.我该如何做到这一点?

My goal is that the completeClass function returns the result of the webworker. How can I make this happen?

this.classWorker = new Worker('app/shared/autocomplete/autocomplete-class-worker.js');

this.completeClass = function(text){
    var self = this;    
    var defer = $q.defer();
    classWorker.postMessage([text, this.oldText, this.oldProposals, this.aliases, this.entityClasses])
};

this.initWorkers = function(){
    var self = this;
    worker.addEventListener('message', function(e) {
        defer.resolve(e.data);
        self.oldProposals = e.data[1];
        self.oldText = text;
        return e.data[0];
    }, false);
};

推荐答案

如果要在上一个调用仍在运行时调用辅助程序,则需要一些东西来排队或跟踪正在进行的请求.我的怀疑是,除非您需要控制请求队列,否则UI线程将请求发射给工作线程更为简单,因此浏览器实质上会将请求排队给您.

If you are going to call the worker when the previous call is still running, then you need something to either queue or keep track of in-progress requests. My suspicion is that unless you need control of the queue of requests, it's simpler for UI thread to fire off the requests to the worker, so the browser essentially queues the requests for you.

但是您仍然需要跟踪以某种方式发送的请求,因此,当您收到来自工作人员的消息时,您知道它正在响应哪个请求.您可以在主线程中完成此操作

But you would still need to keep track of the requests sent somehow, so when you get a message back from the worker, you know which one it is responding do. You can do this by, in the main thread

  • 为每个请求生成唯一的ID.在许多情况下,不断增加的整数就足够了.
  • 创建一个与ID相关联的延迟对象并将其存储
  • 将请求传递给工作人员,并传递ID
  • 将延迟对象的承诺传递回调用者

然后是工人

  • 接收带有ID的消息
  • 完成工作
  • 将结果和ID一起回发

然后是主线程

  • 接收消息,ID和工作结果.
  • 通过ID检索延迟的对象,并通过工作结果对其进行解析.

为此,您可以使用如下代码.我通过仅将 text 传递给工作人员,并返回了 completeText 来稍微简化您的情况.在实际情况下,您可以添加任何一种方式的更多信息.

To do this, you can use some code like below. I've slightly simplified your case by passing just text to the worker, getting completeText back. You can add more information going either way in a real case.

app.service('AutoComplete', function($q) {
  var id = 0;
  var worker = new Worker('app/shared/autocomplete/autocomplete-class-worker.js');
  var inProgress = {};

  this.completeClass = function(text) {
    var deferred = $q.defer();
    id++;
    var request = {
      id: id,
      text: text
    };
    inProgress[id] = deferred;
    worker.postMessage(request);
    return deferred.promise;
  };

  worker.onmessage = function(e) {
    var response = e.data;
    var id = response.id;
    var type = response.type; // resolve, reject, or notify
    var completeText = response.completeText;
    inProgress[id][type](completeText);
    if (type === 'resolve' || type === 'reject') {
      delete inProgress[id];
    }
  };
});

然后在工作程序中,您可以输入类似以下的代码:

Then in the worker you can have code like:

self.onmessage = function(e) {
  var request = e.data;
  var text = request.text;
  var id = request.id;

  // Do the work here
  var completeText = ...

  var response = {
    id: id,
    type: 'resolve', // Can reject the promise in the main thread if desired
    completeText: completeText
  };

  self.postMessage(response);
};

我的目标是completeClass函数返回Webworker的结果.我该如何做到这一点?

My goal is that the completeClass function returns the result of the webworker. How can I make this happen?

为了澄清起见,它不能直接返回结果,因为结果是异步计算的,并且所有函数调用都必须同步返回.但是它可以返回一个承诺,稍后可以解决该问题,例如 $ http 那样.要使用以上内容,您可以执行类似的操作

To clarify, it can't directly return the result, because the result is calculated asynchronously, and all function calls must return synchronously. But it can return a promise that resolves to the result later, just like $http does for example. To use the above, you can do something like

app.controller('MyController', function($scope, AutoComplete) {
   $scope.complete = function(text) {
     AutoComplete.completeClass(text).then(function(result) {
       // Do something with result
     });
   });
});


注意:从技术上讲,如果工作人员对一个请求同步完成所有工作,则无需将ID与每个请求一起传递,因此可以按接收到的顺序响应每个调用.在上面的示例中,主线程始终可以假定对工作线程的调用构成先进先出队列.但是,传递ID可使工作人员灵活地按接收顺序完成工作.说在更高版本中,它需要执行异步操作,例如调用另一个工作程序或发出ajax请求,此方法将允许这样做.


Note: technically, passing an ID along with each request isn't necessary if the worker does all its' work synchronously on one request, and so responds to each call in the order received. In the above example, the main thread can always assume the calls to the worker make a first-in-first-out queue. However, passing an ID gives the flexibility of the worker not finishing the work in the order received. Say in a later version it needs to do something asynchronous, like call another worker, or make an ajax request, this method will allow that.

这篇关于Webworker回调后返回结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆