gpt4 book ai didi

javascript - 如何与 SharedWorker 共享数据

转载 作者:行者123 更新时间:2023-12-05 00:45:19 32 4
gpt4 key购买 nike

互联网上有很多关于 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 也是如此。似乎在大多数情况下,普通的敬业 worker 就足够了。

最佳答案

所以基本上你使用 SharedWorkers 是错误的。

来自文档:https://developer.mozilla.org/de/docs/Web/API/SharedWorker

The SharedWorker interface represents a specific kind of worker that can be accessed from several browsing contexts, such as several windows, iframes or even workers.

这意味着您可以跨多个窗口/选项卡/浏览上下文交流和计算内容

|-----------|    |-----------|
| Window 1 | | Window 2 |
| | | |
| | | |
|-----------| |-----------|
| |
__________________
|
|-----------|
| Worker |
| |
|-----------|

在上下文中发送启动 worker 将在 SharedWorker 上打开一个端口

//============================================
//== Site Script
//============================================

var worker = new SharedWorker('something.js');
worker.port.start(); // this will trigger the on connect event on the webworker
// this will also start the worker IF this is the first call!

// recieve message from worker
worker.port.addEventListener('message', message => {
console.log(message);
});

// send a mesasge to the worker
worker.port.postMessage(['I have a nice message for all']);



//============================================
//== Shared Worker
//============================================
const allPorts = [];

onconnect = function(e) {
// the incoming port
var port = e.ports[0];
allPorts.push(port);

port.addEventListener('message', function(e) {
// get the message sent to the worker
var message = e.data[0];
// send the message to ALL connected worker ports!
allPorts.forEach(port => {
port.postMessage(message);
})
});

port.start(); // Required when using addEventListener. Otherwise called implicitly by onmessage setter.
}

您可以将 Additional Ports 发送给 worker,但 MessagePorts 是 Transferable 对象。这些需要在发送时添加到传输列表中。

const startA = document.getElementById('startA');
const startB = document.getElementById('startB');

const workerScript = 'console.log("started")';
const blob = new Blob([workerScript]);
const workerScriptURL = URL.createObjectURL(blob);

const worker = new Worker(workerScriptURL);
const messageChannel = new MessageChannel();

worker.postMessage({port: messageChannel.port2}, [messageChannel.port2]);
// ^ This is the transfer list!

如果您只想将数据传递到其他上下文,请使用 BrodcastChannel:

https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API

** 编辑 **

这是一个工作演示。尝试在一个选项卡上打开 shared.html,在另一个选项卡上打开 shared2.html。您将在第二个选项卡上看到,数字不会从 0 开始。

(shared.html)

<!DOCTYPE html><html><head></head><body>
<button onclick="init()">Initiate</button>
<script>

function init() {
w = (new SharedWorker('./shared.js')).port;
w.start();
w.postMessage(0);
w.onmessage=e=>{
console.log(e.data);
w.postMessage(e.data[0]+1);
};
}

</script></body></html>

(shared2.html)

<!DOCTYPE html><html><head></head><body>
<button onclick="init()">Initiate</button>
<script>

function init() {
w = (new SharedWorker('./shared.js')).port;
w.start();
w.onmessage=e=>{
console.log(e.data);
};
}

</script></body></html>

(shared.js)

const ports = [];

onconnect = function (ev) {
let port = ev.ports[0];
port.onmessage = (e) => {
setTimeout(()=>{
ports.forEach(p=>p.postMessage([e.data, ev.ports.length]));
},300);
}
port.start();
ports.push(port);
}

关于javascript - 如何与 SharedWorker 共享数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64181873/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com