- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
互联网上有很多关于 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/
MDN Documentation on SharedWorkers状态: The SharedWorker interface represents a specific kind of worke
我需要做一些繁重的工作,发现重新格式化整个代码有点乏味,并且想知道“SharedWorkers 可以使用其他共享工作人员的全局变量吗?”。 如果可以的话,有人可以做一个简单的演示吗?我对 Shared
假设我的 html 文件来自 http://foo.com/index.html ,其中有一个标记为http://bar.com/bar.js 。在 bar.js 中,我想启动一个 SharedWor
我曾与 Worker objects before 合作过,而且非常简单,尤其是教程。 所以下一步自然是 work with SharedWorkers 。我已经把它记下来了,但现在 SharedWo
互联网上有很多关于 SharedWorker 和 StackOverflow 的讨论和教程,但没有一个真正实现了最基本的目标——在两个共享 Worker 之间直接传递数据。 对我来说,SharedWo
在 Chrome 和 Firefox 中 const myWorker = new SharedWorker( "sharedWorkerChat.js" ); const port
使用给定的 tsconfig.json, { "compilerOptions": { "lib": ["es2015", "dom"] }, "files": [
我正在对 HTML5 Web Worker 进行一些研究。我让“普通”工作人员运行良好,但是我似乎无法初始化 SharedWorker。我已经在最新版本的 Chrome 和 Firefox 中尝试过,
我想创建一个 SharedWorker,如一本优秀书籍的一章所述:https://github.com/getify/You-Dont-Know-JS/blob/master/async%20%26%
SharedWorker 使用 Message Port 与 ParentWorker 交换消息。 父工 var port = new SharedWorker('/worker.js').port;
我用纯 JS 创建了一个简单的共享工作程序演示,我决定看看是否可以将其更改为 TS 项目,但从一开始我就遇到了一个问题,我不确定它是否与d.ts 文件或其他文件。 我已经安装了@types/share
使用 new Worker("whatever.js") 生成 WebWorker 工作正常,但 new SharedWorker("whatever.js") 返回错误:ReferenceError
将 SharedWorker 添加到 @angular/cli >1.2 生成的项目的具体步骤是什么。我希望 SharedWorker 在 TypeScript 中定义(具有完整/正确的类型定义编辑器
为什么 Safari 放弃了对 SharedWorker 的支持? 是否有任何有效的 polyfill 使用例如 localStorage 和 StorageEvent 作为通信端口? (是的,shi
在我见过的所有例子中,它们都与此类似 onconnect = function(e) { var port = e.ports[0]; port.onmessage = functio
我正在尝试在 SharedWorker 中实现服务器发送事件 (SSE)。 实现在谷歌浏览器中没有问题。但是,它在 FireFox 中根本不起作用。 当我尝试让它在 FireFox 中运行时,我在控制
我试图让每个在我的应用程序上打开多个选项卡的用户只保持一个连接事件,该应用程序使用 Pusher 和 Laravel Echo,我能够按照下面的文章和示例项目让它在测试项目上工作。 https://b
我是一名优秀的程序员,十分优秀!