JavaScript postMessage 和多个可传输对象

JavaScript postMessage and multiple transferable objects

我正在尝试使用实验性 Canvas 功能 - 屏幕外Canvas。

index.html

<html>
  <body>
    <canvas id="myCanvas" width="400" height="400"></canvas>
  </body>

  <script>
    const canvas = document.querySelector('#myCanvas');
    const offscreenCanvas = canvas.transferControlToOffscreen();

    const worker = new Worker('./worker.js');
    worker.postMessage({offscreenCanvas}, [offscreenCanvas]);

  </script>
</html>


worker.js

onmessage = e => {
  const ctx = e.data.offscreenCanvas.getContext('2d');

  ctx.fillRect(0 , 0, 100 , 100);
  ctx.commit();
}

这里一切正常,我在 canvas 上绘制了简单的矩形。现在 - 如何使用 postMessage 传递附加信息?例如 - 是否可以发送具有矩形坐标的对象?

喜欢

const obj = {
  x: 0,
  y: 0,
}

我尝试通过创建新的 Int8Array 来使用可转移对象:

const bufferObj = new Int8Array([obj.x, obj.y]);

老实说,我不知道如何将它发送给工作人员并从事件对象中读取它。我在考虑

worker.postMessage(offscreenCanvas, bufferObj, [offscreenCanvas, bufferObj]);

但这会抛出错误 索引 1 处的值没有可转移类型。知道如何解决这个问题吗?

首先,如果您不需要转让对象的所有权,而只是将其发送给工作人员,您可以这样做:

const obj = {
  x: 0,
  y: 0,
}

worker.postMessage({offscreenCanvas, obj}, [offscreenCanvas]);

然后从工作人员访问 e.data.obj 没有问题。对于简单的对象,我会说这不是主要问题,因为 postMessage 使用 Structured clone algorithm

但是,如果您需要优化,并且传递大量数据 – 作为屏幕外 canvas – 您希望将对象转移到另一侧。

在这种情况下,您的错误是使用了未实现 Transferable 接口的 Typed Array。相反,您必须通过 ArrayBuffer。例如:

const buff = new Uint8Array([obj.x, obj.y]).buffer;

worker.postMessage({offscreenCanvas, buff}, [offscreenCanvas, buff]);

应该可以。