如何从Web工作者调用共享工作者?

时间:2015-06-14 13:34:28

标签: javascript web-worker shared-worker

是否可以从Web Worker调用共享工作者?

请你举个例子。

在我的情况下,我有一些网络工作者,我需要在他们之间共享单身服务。

2 个答案:

答案 0 :(得分:6)

您可以使用与https://stackoverflow.com/a/30796101/1319998类似的技术。对于每个专用工作器,您可以创建一个共享工作器对象,指向同一个脚本,并将其端口传递给专用工作器。

请注意,对于相同的脚本URL,new SharedWorker(scriptUrl)并不一定要创建新的共享工作线程:它只是创建一个新对象,允许您与共享工作线程进行通信,并且只创建如果它已经存在则自行穿线。

作为示例,以下内容创建了2个Worker个对象,每个对象创建一个单独的专用工作线程,以及2个SharedWorker个对象,这些对象总共创建了一个共享工作线程。共享工作程序的端口对象将传递给专用worker:

var sharedWorkerA = new SharedWorker("worker-shared.js");
sharedWorkerA.port.start();

var dedicatedWorkerA = new Worker("worker-dedicated.js");
dedicatedWorkerA.postMessage({sharedWorkerPort: sharedWorkerA.port, workerName: 'A'}, [sharedWorkerA.port]);

var sharedWorkerB = new SharedWorker("worker-shared.js");
sharedWorkerB.port.start();

var dedicatedWorkerB = new Worker("worker-dedicated.js");
dedicatedWorkerB.postMessage({sharedWorkerPort: sharedWorkerB.port, workerName: 'B'}, [sharedWorkerB.port]);

然后,专职工作人员可以在收到的端口对象上发布消息:

self.onmessage = function(e) {
  var workerName = e.data.workerName;
  var sharedWorkerPort = e.data.sharedWorkerPort;

  self.setInterval(function() {
    sharedWorkerPort.postMessage('sent from dedicated worker ' + workerName);
  }, 2000);
};

共享工作人员可以接收它们:

var num = 0;
self.onconnect = function(e) {
  console.log('shared connect');
  var port = e.ports[0];

  port.onmessage = function(e) {
    num++;
    console.log('Received in shared worker: ', e.data);
    console.log('Number of messaged received:', num);
  };
};

我在那里放了一些额外的代码,只是为了表明确实有一个实际的共享工作线程正在运行。您可以在http://plnkr.co/edit/RcxxY2EDIcclUegC82wG?p=preview

看到上述工作

答案 1 :(得分:3)

SharedWorker中的WorkerGlobalScope构造函数当前不可用,因此您将无法像在iframe或窗口中那样构建实例。

您可以做的是,为每个工作人员创建一个MessageChannel,并使用它在worker和sharedWorker之间进行通信。虽然这样做会否定实际SharedWorker的需要,因为您也可以使用单个Worker

示例:

var numWorkers = 4;
var sharedWorker = new Worker("worker-shared.js");

for(var i = 0; i < numWorkers; i++) {
  var dedicatedWorker = new Worker("worker-dedicated.js");
  var channel = new MessageChannel();
  dedicatedWorker.postMessage({sharedWorkerPort: channel.port1}, [channel.port1]);
  sharedWorker.postMessage({workerPort: channel.port2}, [channel.port2]);
}

Demo