当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


Node.js MessagePort port.postMessage(value[, transferList])用法及代码示例


port.postMessage(value[, transferList])

历史
版本变化
v15.6.0

X509Certificate 添加到可克隆类型列表中。

v15.0.0

CryptoKey 添加到可克隆类型列表中。

v15.14.0、v14.18.0

将'BlockList' 添加到可克隆类型列表中。

v15.9.0、v14.18.0

将 'Histogram' 类型添加到可克隆类型列表中。

v14.5.0、v12.19.0

KeyObject 添加到可克隆类型列表中。

v14.5.0、v12.19.0

FileHandle 添加到可转移类型列表中。

v10.5.0

添加于:v10.5.0


参数

将 JavaScript 值发送到此通道的接收端。 value 以与 HTML structured clone algorithm 兼容的方式传输。

特别是,与JSON 的显著差异是:

const { MessageChannel } = require('node:worker_threads');
const { port1, port2 } = new MessageChannel();

port1.on('message', (message) => console.log(message));

const circularData = {};
circularData.foo = circularData;
// Prints: { foo: [Circular] }
port2.postMessage(circularData);

transferList 可能是 ArrayBuffer MessagePort FileHandle 对象的列表。传输后,它们在通道的发送端不再可用(即使它们不包含在 value 中)。与 child processes 不同,目前不支持传输网络套接字等句柄。

如果 value 包含 SharedArrayBuffer 实例,则可以从任一线程访问这些实例。它们不能在 transferList 中列出。

value 可能仍包含不在 transferList 中的 ArrayBuffer 实例;在这种情况下,底层内存被复制而不是移动。

const { MessageChannel } = require('node:worker_threads');
const { port1, port2 } = new MessageChannel();

port1.on('message', (message) => console.log(message));

const uint8Array = new Uint8Array([ 1, 2, 3, 4 ]);
// This posts a copy of `uint8Array`:
port2.postMessage(uint8Array);
// This does not copy data, but renders `uint8Array` unusable:
port2.postMessage(uint8Array, [ uint8Array.buffer ]);

// The memory for the `sharedUint8Array` is accessible from both the
// original and the copy received by `.on('message')`:
const sharedUint8Array = new Uint8Array(new SharedArrayBuffer(4));
port2.postMessage(sharedUint8Array);

// This transfers a freshly created message port to the receiver.
// This can be used, for example, to create communication channels between
// multiple `Worker` threads that are children of the same parent thread.
const otherChannel = new MessageChannel();
port2.postMessage({ port: otherChannel.port1 }, [ otherChannel.port1 ]);

消息对象立即克隆,发布后可以修改,没有副作用。

有关此 API 背后的序列化和反序列化机制的更多信息,请参阅 node:v8 模块的序列化 API。

传输TypedArrays 和缓冲区时的注意事项#

所有 TypedArrayBuffer 实例都是底层 ArrayBuffer 的视图。也就是说,实际存储原始数据的是ArrayBuffer,而TypedArrayBuffer 对象提供了一种查看和操作数据的方式。在同一个 ArrayBuffer 实例上创建多个视图是可能的并且很常见。使用传输列表传输ArrayBuffer 时必须非常小心,因为这样做会导致共享相同ArrayBuffer 的所有TypedArrayBuffer 实例变得不可用。

const ab = new ArrayBuffer(10);

const u1 = new Uint8Array(ab);
const u2 = new Uint16Array(ab);

console.log(u2.length);  // prints 5

port.postMessage(u1, [u1.buffer]);

console.log(u2.length);  // prints 0

对于Buffer 实例,具体而言,底层ArrayBuffer 是否可以传输或克隆完全取决于实例的创建方式,而这通常无法可靠地确定。

ArrayBuffer 可以用 markAsUntransferable() 标记,以指示它应该始终被克隆并且永远不会转移。

根据 Buffer 实例的创建方式,它可能拥有也可能不拥有其底层 ArrayBuffer 。除非已知 Buffer 实例拥有它,否则不得转移 ArrayBuffer。特别是,对于从内部 Buffer 池创建的 Buffer(例如使用 Buffer.from()Buffer.allocUnsafe() ),无法传输它们并且它们总是被克隆,这会发送整个 Buffer 的副本水池。此行为可能会带来意外的更高内存使用率和可能的安全问题。

有关Buffer 池的更多详细信息,请参阅 Buffer.allocUnsafe()

使用 Buffer.alloc()Buffer.allocUnsafeSlow() 创建的 Buffer 实例的 ArrayBuffer 始终可以传输,但这样做会使这些 ArrayBuffer 的所有其他现有视图不可用。

使用原型、类和访问器克隆对象时的注意事项#

因为对象克隆使用 HTML structured clone algorithm ,所以不保留不可枚举的属性、属性访问器和对象原型。特别是, Buffer 对象将在接收端被读取为普通的 Uint8Array s,并且 JavaScript 类的实例将被克隆为普通的 JavaScript 对象。

const b = Symbol('b');

class Foo {
  #a = 1;
  constructor() {
    this[b] = 2;
    this.c = 3;
  }

  get d() { return 4; }
}

const { port1, port2 } = new MessageChannel();

port1.onmessage = ({ data }) => console.log(data);

port2.postMessage(new Foo());

// Prints: { c: 3 }

此限制扩展到许多内置对象,例如全局 URL 对象:

const { port1, port2 } = new MessageChannel();

port1.onmessage = ({ data }) => console.log(data);

port2.postMessage(new URL('https://example.org'));

// Prints: { }

相关用法


注:本文由纯净天空筛选整理自nodejs.org大神的英文原创作品 port.postMessage(value[, transferList])。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。