port.postMessage(value[, transferList])


将一个 JavaScript 值发送到此通道的接收端。value 以与 HTML 结构化克隆算法 兼容的方式进行传输。

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

特别是,与 JSON 的显著区别如下:

🌐 In particular, the significant differences to JSON are:

import { MessageChannel } from '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);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>MessagePortFileHandle<net.Server><net.Socket> 对象的列表。传输后,它们在通道的发送端就不能再使用了(即使它们不在 value 中)。

转移一个 <net.Server> 会把它的监听套接字——连同在接收队列中的任何待处理连接——移动到接收线程的事件循环中。转移一个 <net.Socket> 会移动一个单独的连接;这个套接字必须是新接受或新创建的 TCP 连接,而且还没有开始读取,也没有缓冲数据,否则 postMessage() 会抛出 ERR_WORKER_HANDLE_NOT_TRANSFERABLE。这样就可以在一个线程上接受连接,然后把它们分配到一组工作线程中。只支持 TCP 句柄。

🌐 Transferring a <net.Server> moves its listening socket — together with any pending connections in the accept queue — to the receiving thread's event loop. Transferring a <net.Socket> moves a single connection; the socket must be a freshly accepted or created TCP connection that has not yet started reading and has no buffered data, otherwise postMessage() throws ERR_WORKER_HANDLE_NOT_TRANSFERABLE. This makes it possible to accept connections on one thread and distribute them across a pool of worker threads. Only TCP handles are supported.

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

🌐 If value contains <SharedArrayBuffer> instances, those are accessible from either thread. They cannot be listed in transferList.

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

import { MessageChannel } from '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 ]);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 ]);

消息对象会被立即克隆,并且在发布后可以修改而不会产生副作用。

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

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

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