port.postMessage(value[, transferList])


向该通道的接收端发送 JavaScript 值。 value 将以与 HTML 结构化克隆算法兼容的方式传输。

特别是与 JSON 的显着区别是:

  • value 可能包含循环引用。
  • value 可能包含内置 JS 类型的实例,例如 RegExpBigIntMapSet 等。
  • value 可能包含类型化数组,都使用 ArrayBufferSharedArrayBuffer
  • value 可能包含 WebAssembly.Module 实例。
const { MessageChannel } = require('worker_threads');
const { port1, port2 } = new MessageChannel();

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

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

transferList 可能是 ArrayBufferMessagePortFileHandle 对象的列表。 传输后,它们将不再能在通道的发送端使用(即使它们不包含在 value 中) 与子进程不同,当前不支持传输句柄,例如网络套接字。

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

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

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

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

const uint8Array = new Uint8Array([ 1, 2, 3, 4 ]);
// 此发送 `uint8Array` 的副本:
port2.postMessage(uint8Array);
// 这不会复制数据,但会使 `uint8Array` 无法使用:
port2.postMessage(uint8Array, [ uint8Array.buffer ]);

// `sharedUint8Array` 的内存可以从
// `.on('message')` 收到的原件和副本中访问:
const sharedUint8Array = new Uint8Array(new SharedArrayBuffer(4));
port2.postMessage(sharedUint8Array);

// 这会将新创建的消息端口传输到接收器。
// 例如,这可用于在作为同一父线程的子线程的多个 `Worker` 线程之间
// 创建通信通道。
const otherChannel = new MessageChannel();
port2.postMessage({ port: otherChannel.port1 }, [ otherChannel.port1 ]);

因为对象克隆使用结构化克隆算法,不可枚举的属性、属性访问器和对象原型不会被保留。 特别是,Buffer 对象将在接收方读取为普通的 Uint8Array

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

关于此 API 背后的序列化和反序列化机制的更多信息,请参见 v8 模块的序列化 API

Sends a JavaScript value to the receiving side of this channel. value will be transferred in a way which is compatible with the HTML structured clone algorithm.

In particular, the significant differences to JSON are:

  • value may contain circular references.
  • value may contain instances of builtin JS types such as RegExps, BigInts, Maps, Sets, etc.
  • value may contain typed arrays, both using ArrayBuffers and SharedArrayBuffers.
  • value may contain WebAssembly.Module instances.
  • value may not contain native (C++-backed) objects other than MessagePorts, FileHandles, and KeyObjects.
const { MessageChannel } = require('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 may be a list of ArrayBuffer, MessagePort and FileHandle objects. After transferring, they will not be usable on the sending side of the channel anymore (even if they are not contained in value). Unlike with child processes, transferring handles such as network sockets is currently not supported.

If value contains SharedArrayBuffer instances, those will be accessible from either thread. They cannot be listed in transferList.

value may still contain ArrayBuffer instances that are not in transferList; in that case, the underlying memory is copied rather than moved.

const { MessageChannel } = require('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` will be 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 ]);

Because the object cloning uses the structured clone algorithm, non-enumerable properties, property accessors, and object prototypes are not preserved. In particular, Buffer objects will be read as plain Uint8Arrays on the receiving side.

The message object will be cloned immediately, and can be modified after posting without having side effects.

For more information on the serialization and deserialization mechanisms behind this API, see the serialization API of the v8 module.