Javascript 使用来自Web Worker的可转移对象

Javascript 使用来自Web Worker的可转移对象,javascript,web-worker,transferable,Javascript,Web Worker,Transferable,我目前有以下代码来创建Web Worker: w = new Worker("webwork.js"); w.onmessage = function(event) { alert(event.data); } self.onmessage = function(event) { //var ss=r; //Causes error because of undefined var ss=""; for(var currProp in event) {

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

w = new Worker("webwork.js");
w.onmessage = function(event) { alert(event.data); }
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);
}
然后是Web工作者的
webwork.js
代码:

w = new Worker("webwork.js");
w.onmessage = function(event) { alert(event.data); }
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工作者本身访问它呢。我已经尝试过
event.r
,只是
r
self.r
以及其他类似的事情,比如尝试为
ArrayBuffers
数组添加第二个函数参数,但没有任何效果

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

请尝试w.postMessage([0,r])。要使用可转移对象,需要将数组缓冲区作为数组中的第二项传递。请参见

这对我很有用:

//大体上

var x = new ArrayBuffer(1048576*128);
w.postMessage({buffer: x});
//在工作线程的消息处理程序中

processMessage: function(ev){
    var buffer = ev.data.buffer,
    // other stuff . buffer is referenced correctly here. 
}

sbr给出的答案是可行的,但它会导致在发送给工人之前制作一份数据副本。对于大量数据来说,这可能会很慢
要使用“可转移对象”,实际上是将对象的所有权转移给web worker或从web worker转移出去。这就像在没有复制的地方通过引用一样。它与正常的按引用传递之间的区别在于,传输数据的一方不再能够访问它。

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

w.postMessage(r,[r]);  // first arg is r, not 0 as in the question
以及您在web worker中访问它的方式:

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

在我自己的应用程序中,我需要将一个大型类型的Float64Array从web worker发送到主线程,而不会受到副本性能的影响。这需要大量的尝试、错误和搜索,因此我想我应该在这里为遇到类似问题的其他人提供该示例。
这是在工作者端工作的代码(arr是我的Float64Array):

在接收主线程上,我有:

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]);
在接收线程(本例中为主线程)上:

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

var objData =
{
    str: "string",
    ab: new ArrayBuffer(100),
    i8: new Int8Array(200)
};
objWorker.postMessage(objData, [objData.ab, objData.i8.buffer]);
另一方面:

self.onmessage = function(objEvent)
{
    var strText = objEvent.data.str;
    var objTypedArray = objEvent.data.ab;
    var objTypedArrayView = objEvent.data.i8;
}

它不是在
事件中吗。数据
?似乎不是这样。如果我使用“w.postMessage(0,[r]);”,那么“event.data”就是0,但我不知道ArrayBuffers数组的位置,即使通过检查事件的所有属性也是如此。我找不到。这只会克隆ArrayBuffer;不在线程之间转移所有权。有人知道这是转移所有权还是复制所有权吗?我试过了,它看起来像是转移了所有权。只创建一次ArrayBuffer和Int8Array!然后继续来回发送。否则,使用可转移的对象就毫无意义了。@Pawel你能详细说明一下如何不断地来回发送它吗?一旦你收到数组,如果你试图再次发送后消息,浏览器会抱怨“索引0处的ArrayBuffer已被阉割。”@dooderson回答得有点晚,但对后代来说:是的,这会转移所有权()。我假设它是为了保持原子性这个答案比公认的答案好,因为它更好地解释了第二个数组参数的用途。
self.onmessage = function(objEvent)
{
    var strText = objEvent.data.str;
    var objTypedArray = objEvent.data.ab;
    var objTypedArrayView = objEvent.data.i8;
}