是否可以将传输的 ArrayBuffer 返回原始类型数组?

Igo*_*ush 3 javascript multithreading web-worker

据我所知,将对象传输到 Web Worker 会导致主线程失去所有权。我想知道是否有什么办法可以让它重新获得所有权。这个Plunker(下面的代码)演示了我遇到的问题。

main.js

var worker = new Worker("worker.js");
var z = new Int16Array(10);
worker.onmessage = function(e) {
    console.log(e.data);  // [0, 1, ... 10]
    console.log(z);  // [], ownership not regained here
}
console.log(z);  // [0, 0, ... 0], original value here
worker.postMessage(z, [z.buffer]);
console.log(z);  // [], ownership lost here
Run Code Online (Sandbox Code Playgroud)

工人.js

self.onmessage = function(e) {
    var data = e.data;  // transferred "z" from main.js
    for (var i = 0; i < 10; i++) {
        data[i] = i;
    }
    // I thought this would return ownership back to the main thread
    self.postMessage(data, [data.buffer]);
}
Run Code Online (Sandbox Code Playgroud)

本质上,最终目标是从工作线程内更改z主线程中的值,而不必在收到消息后在主线程中复制结果。然而,所有权似乎z仍由工人保留。我误解了什么吗?有办法做到这一点吗?

非常感谢任何建议。

Tom*_*ica 5

不,事情不是这样的。它Int16Array只是一个封装了 的接口ArrayBuffer,它是真正的二进制数据存储的地方。当您转移所有权时,Int16Array就失效(设置为 0 长度)。在您的工作线程中,新的Int16Array被创建并分配给旧的ArrayBuffer。我为你制作了这张图片:

图片描述

  1. 发布消息从类型化数组中删除缓冲区。
  2. 所有不可传输的(即ArrayBuffer)都被序列化为结构化克隆,数组缓冲区被传输
  3. Int16Array对象不再有缓冲区,因此无效
  4. 结构化克隆被反序列化并创建新Int16Array实例,该实例接收传输的 ArrayBuffer

显然,解释器无法知道您返回了后面ArrayBuffer,因此类型化数组永远无效。