【发布时间】:2020-10-03 07:44:11
【问题描述】:
互联网上有很多关于 SharedWorker 和 StackOverflow 的讨论和教程,但没有一个真正实现了最基本的目标——在两个共享 Worker 之间直接传递数据。
对我来说,SharedWorker 相对于专用 Web Worker 的优势在于前者允许通过不同的选项卡、iframe 和线程进行直接通信。我尝试了以下方法:
(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();
}
单击“启动 A”,然后单击“启动 B”后,我在控制台上收到以下错误消息:
shared.html:15 未捕获的 DOMException:无法在“MessagePort”上执行“postMessage”:无法克隆 MessagePort,因为它没有被传输。
换句话说,我无法通过端口。
SharedWorker 也是如此。似乎在大多数情况下,普通的敬业工人就足够了。
【问题讨论】:
-
你到底想做什么?你为什么尝试发送消息端口与工人交谈?但基本上,要发送一个端口,您需要在 transferList
b.postMessage({type:'start', port:a}, [a]);中引用它。 -
我正在尝试让工人 a 直接与工人 b 交谈。
-
但是由于这是sharedWorker,所以这些都是一样的。
-
你是说SharedWorker只能有一个?
-
不,我是说:如果两个共享工作者被同一个脚本在同一个源上加载,它只会产生一个共享工作者。你可以有多个 Shared Worker,但是你需要多个脚本。在您的示例中,您使用相同的脚本/文件/代码初始化它们。所以应该只有一个实例。
标签: javascript web worker webapi shared-worker