port.postMessage(value[, transferList])
value
<any>transferList
<Object[]>
向该通道的接收端发送 JavaScript 值。
value
将以与 HTML 结构化克隆算法兼容的方式传输。
特别是与 JSON
的显着区别是:
value
可能包含循环引用。value
可能包含内置 JS 类型的实例,例如RegExp
、BigInt
、Map
、Set
等。value
可能包含类型化数组,都使用ArrayBuffer
和SharedArrayBuffer
。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
可能是 ArrayBuffer
、MessagePort
和 FileHandle
对象的列表。
传输后,它们将不再能在通道的发送端使用(即使它们不包含在 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。
value
<any>transferList
<Object[]>
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 asRegExp
s,BigInt
s,Map
s,Set
s, etc.value
may contain typed arrays, both usingArrayBuffer
s andSharedArrayBuffer
s.value
may containWebAssembly.Module
instances.value
may not contain native (C++-backed) objects other thanMessagePort
s,FileHandle
s, andKeyObject
s.
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 Uint8Array
s 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.