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.
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.
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
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