简体   繁体   中英

How to call shared worker from the web worker?

Is it possible to call a Shared Worker from the Web Worker?

Could you please give me an example.

In my case I have a few web workers and I need to share a singleton service between them.

You can use a technique similar to that at https://stackoverflow.com/a/30796101/1319998 . For each dedicated worker, you can create a shared worker object, pointing to the same script, and pass its port to the dedicated worker.

Note that for the same script URL, new SharedWorker(scriptUrl) doesn't necessarily create a new shared worker thread: it just creates a new object that allows you to communicate with the shared worker thread, and only creates the thread itself if it doesn't already exist.

As an example, the following creates 2 Worker objects, that each create a separate dedicated worker thread, and 2 SharedWorker objects, that in total creates one shared worker thread. The port objects of the shared workers are passed to the dedicated workers:

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]);

The dedicated workers can then post messages on the port objects they have received:

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

And the the shared worker can receive them:

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

I've put a bit of extra code in there just to show that there is indeed one actual shared worker thread running. You can see the above working at http://plnkr.co/edit/RcxxY2EDIcclUegC82wG?p=preview

The SharedWorker constructor is not currently available within the WorkerGlobalScope , so you will not be able to construct an instance like you would in an iframe or window.

What you can do is, create a MessageChannel for each of your workers, and use it to communicate between the worker and sharedWorker. Though doing this would negate the need for an actual SharedWorker , since you could just as well use a single Worker instead.

Example:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM