There has been a lot of discussions and tutorials on SharedWorker on the Internet and StackOverflow, but none has really achieved the most basic goal -- passing data directly between two shared workers.
To me, the strength of SharedWorker over a dedicated web Worker is that the former allows direct communication over different tabs, iframes and threads. I tried the following:
(shared.html:)
<!DOCTYPE html><html><head></head><body>
<button onclick="init('a')">Initiate A</button>
<button onclick="init('b')">Initiate B</button>
<script>
var a,b;
function init(v) {
if (v=='a'){
a = (new SharedWorker('./shared.js')).port;
a.start();
a.postMessage({type:'start', port:b})
} else {
b = (new SharedWorker('./shared.js')).port;
b.start();
b.postMessage({type:'start', port:a}); // <== error here
}
}
</script></body></html>
(shared.js)
let peer = null;
onconnect = function (ev) {
let port = ev.ports[0];
port.onmessage = (e) => {
if (e.data.type=='start' && e.data.port){
peer=e.data.port;
} else if (e.data.type=='msg' && peer){
setInterval(()=>{
peer.postMessage({type:'msg',msg:'greetings!'});
},2000);
}
}
port.start();
}
After clicking 'Initiate A' and then 'Initiate B', I got the following error message on the console:
shared.html:15 Uncaught DOMException: Failed to execute 'postMessage' on 'MessagePort': A MessagePort could not be cloned because it was not transferred.
In other words, I couldn't pass the ports around.
So is SharedWorker of any use at all. It seems that the regular dedicated Worker suffices under most circumstances.
So basicly you are using SharedWorkers wrong.
From a documentation: https://developer.mozilla.org/de/docs/Web/API/SharedWorker
That means that you can communicate and compute stuff accross multiple windows / tabs / browsing contexts
Sending starting the worker in a context will open a port on the SharedWorker
You can sen Additional Ports to the worker, but MessagePorts are Transferable objects. These needs to be added to the transfer list when sent.
If you only want to pass data to other contexts though, use a BrodcastChannel:
https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API
** EDIT **
Here is a working demo. Try opening shared.html on one tab and shared2.html on another tab. You will see on the second tab, the number won't start from 0.
(shared.html)
(shared2.html)
(shared.js)