JavaScript postMessage и несколько переносимых объектов

Я пытаюсь использовать экспериментальную функцию Canvas - offscreenCanvas.

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();
}

Здесь все отлично работает, рисую на холсте простой прямоугольник. Теперь - как передать дополнительную информацию с помощью postMessage? Например - можно ли отправить объект с прямоугольными координатами?

Нравиться

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

Я попытался использовать переносимые объекты, создав новый Int8Array:

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

Честно говоря, я не знаю, как отправить его рабочему и прочитать из объекта события. Я думал о

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

Но это вызывает ошибку. Значение с индексом 1 не имеет переносимого типа. Есть идеи, как это решить?


person Amay    schedule 13.06.2018    source источник


Ответы (1)


Во-первых, если вам не нужно передавать право собственности на объект, а просто отправить его работнику, вы можете сделать это:

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

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

А потом просто доступ с рабочего к e.data.obj без проблем. Для простого объекта я бы сказал, что это не серьезная проблема, поскольку postMessage используйте Структурированный алгоритм клонирования

Однако, если вам нужна оптимизация, и вы передаете большой объем данных - как заэкранный холст - вы хотите вместо этого перенести объект на другую сторону.

В таком случае ваша ошибка заключалась в использовании Typed Array, который не реализует интерфейс Transferable. Вместо этого вы должны передать ArrayBuffer. Например:

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

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

Это должно сработать.

person ZER0    schedule 13.06.2018
comment
Вы можете отправить TypedArray как часть первого аргумента, пока его буфер находится во втором аргументе, он будет передан. Ошибка OP заключалась в передаче TypedArray напрямую в качестве второго аргумента, алгоритм postMessage прошел через каждый индекс TypedArray в поисках передаваемого объекта и обнаружил int = ›TypeError - person Kaiido; 14.06.2018