使用来自 Web Worker 的可传输对象

新手上路,请多包涵

我目前有此代码来创建 Web Worker:

 w = new Worker("webwork.js");
w.onmessage = function(event) { alert(event.data); }

然后是 Web Worker 的 webwork.js 代码:

 self.onmessage = function(event) {
    //var ss=r;  //Causes error because of undefined
    var ss="";
    for(var currProp in event) {
        ss+=("event."+currProp+"="+event[currProp]+"\n");
    }
    postMessage(ss);
}

现在我想使用以下代码传输一个 128 兆字节 ArrayBuffer

 var r = new ArrayBuffer(1048576*128);
w.postMessage(0, [r]);


现在我应该已经转移了变量 r ,我如何从 Web Worker 本身访问它。 I have tried event.r , just r , self.r and other things like trying to add a second function argument for the array of ArrayBuffers ,但没有任何效果。

如何从 Web Worker 访问传输的变量?

原文由 alt.126 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.4k
2 个回答
postMesage(aMessage, transferList)

transferList 中,您必须指定 aMessage 中包含的可转移对象:

 const objData = {
    strText: "coolcmd",
    objArrayBuffer: new ArrayBuffer(10),
    objTypedArray: new Int8Array(20)
};
objWorker.postMessage(
    objData,
    [objData.objArrayBuffer, objData.objTypedArray.buffer]
);

在工人中:

 self.onmessage = objEvent => {
    console.log(
        objEvent.data.strText,
        objEvent.data.objArrayBuffer,
        objEvent.data.objTypedArray
    );
};

或者使用 对象解构

 self.onmessage = ({data: {strText, objArrayBuffer, objTypedArray}}) => {
    console.log(
        strText,
        objArrayBuffer,
        objTypedArray
    );
};

可转让对象 清单

原文由 CoolCmd 发布,翻译遵循 CC BY-SA 4.0 许可协议

sbr 给出的答案有效,但它会导致在发送给工作人员之前制作数据副本。对于大量数据,这可能会很慢。

要使用“可转移对象”,您实际上是将对象的所有权转移给 web worker 或从 web worker 转移。这就像在没有复制的情况下通过引用传递。它与普通引用传递的区别在于,传输数据的一方无法再访问它。

我相信您应该在示例中发送数据的方式是:

 w.postMessage(r,[r]);  // first arg is r, not 0 as in the question

以及您在网络工作者中访问它的方式:

 addEventListener('message', function(event) {
    var r = event.data;
});


在我自己的应用程序中,我需要将一个大类型的 Float64Array 从 web worker 发送到主线程,而不需要复制的性能损失。这需要大量的反复试验和搜索,所以我想我应该在这里为遇到类似问题的任何其他人提供该示例。

这是在工作端工作的代码(arr 是我的 Float64Array):

 self.postMessage(arr.buffer, [arr.buffer]);

在接收主线程上,我有:

 theWorker.addEventListener('message', function(ev) {
    var arr = new Float64Array(ev.data);  // just cast it to the desired type - no copy made
    // ...
});

请注意,这适用于 Chrome,但截至目前可能不适用于大多数其他浏览器(尚未尝试)。

另外,如果你想发送除了大数组之外的其他信息,你可以这样做:

 self.postMessage({foo:"foo", bar:arr.buffer}, [arr.buffer]);

在接收(在这个例子中是主线程)上:

 theWorker.addEventListener('message', function(event) {
    var foo = event.data.foo;
    var arr = new Float64Array(event.data.bar);  // cast it to the desired type
    // ...
});

原文由 Lawrence 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题