- assert 断言
- async_hooks 异步钩子
- async_hooks/context 异步上下文
- buffer 缓冲区
- C++插件
- C/C++插件(使用 Node-API)
- C++嵌入器
- child_process 子进程
- cluster 集群
- CLI 命令行
- console 控制台
- Corepack 核心包
- crypto 加密
- crypto/webcrypto 网络加密
- debugger 调试器
- deprecation 弃用
- dgram 数据报
- diagnostics_channel 诊断通道
- dns 域名服务器
- domain 域
- Error 错误
- events 事件触发器
- fs 文件系统
- global 全局变量
- http 超文本传输协议
- http2 超文本传输协议 2.0
- https 安全超文本传输协议
- inspector 检查器
- Intl 国际化
- module 模块
- module/cjs CommonJS 模块
- module/esm ECMAScript 模块
- module/package 包模块
- module/typescript TS 模块
- net 网络
- os 操作系统
- path 路径
- perf_hooks 性能钩子
- permission 权限
- process 进程
- punycode 域名代码
- querystring 查询字符串
- readline 逐行读取
- repl 交互式解释器
- report 诊断报告
- sea 单个可执行应用程序
Node.js v22.12.0 文档
- Node.js v22.12.0
-
目录
- 工作线程
worker.getEnvironmentData(key)
worker.isMainThread
worker.markAsUntransferable(object)
worker.isMarkedAsUntransferable(object)
worker.markAsUncloneable(object)
worker.moveMessagePortToContext(port, contextifiedSandbox)
worker.parentPort
worker.postMessageToThread(threadId, value[, transferList][, timeout])
worker.receiveMessageOnPort(port)
worker.resourceLimits
worker.SHARE_ENV
worker.setEnvironmentData(key[, value])
worker.threadId
worker.workerData
- 类:
BroadcastChannel extends EventTarget
- 类:
MessageChannel
- 类:
MessagePort
- 类:
Worker
new Worker(filename[, options])
- 事件:
'error'
- 事件:
'exit'
- 事件:
'message'
- 事件:
'messageerror'
- 事件:
'online'
worker.getHeapSnapshot([options])
worker.performance
worker.postMessage(value[, transferList])
worker.ref()
worker.resourceLimits
worker.stderr
worker.stdin
worker.stdout
worker.terminate()
worker.threadId
worker.unref()
- 注意事项
- 工作线程
-
导航
- assert 断言
- async_hooks 异步钩子
- async_hooks/context 异步上下文
- buffer 缓冲区
- C++插件
- C/C++插件(使用 Node-API)
- C++嵌入器
- child_process 子进程
- cluster 集群
- CLI 命令行
- console 控制台
- Corepack 核心包
- crypto 加密
- crypto/webcrypto 网络加密
- debugger 调试器
- deprecation 弃用
- dgram 数据报
- diagnostics_channel 诊断通道
- dns 域名服务器
- domain 域
- Error 错误
- events 事件触发器
- fs 文件系统
- global 全局变量
- http 超文本传输协议
- http2 超文本传输协议 2.0
- https 安全超文本传输协议
- inspector 检查器
- Intl 国际化
- module 模块
- module/cjs CommonJS 模块
- module/esm ECMAScript 模块
- module/package 包模块
- module/typescript TS 模块
- net 网络
- os 操作系统
- path 路径
- perf_hooks 性能钩子
- permission 权限
- process 进程
- punycode 域名代码
- querystring 查询字符串
- readline 逐行读取
- repl 交互式解释器
- report 诊断报告
- sea 单个可执行应用程序
- 其他版本
工作线程#
¥Worker threads
¥Stability: 2 - Stable
node:worker_threads
模块允许使用并行执行 JavaScript 的线程。要访问它:
¥The node:worker_threads
module enables the use of threads that execute
JavaScript in parallel. To access it:
const worker = require('node:worker_threads');
工作线程对于执行 CPU 密集型的 JavaScript 操作很有用。它们对 I/O 密集型的工作帮助不大。Node.js 内置的异步 I/O 操作比工作线程更高效。
¥Workers (threads) are useful for performing CPU-intensive JavaScript operations. They do not help much with I/O-intensive work. The Node.js built-in asynchronous I/O operations are more efficient than Workers can be.
与 child_process
或 cluster
不同,worker_threads
可以共享内存。它们通过传输 ArrayBuffer
实例或共享 SharedArrayBuffer
实例来实现。
¥Unlike child_process
or cluster
, worker_threads
can share memory. They do
so by transferring ArrayBuffer
instances or sharing SharedArrayBuffer
instances.
const {
Worker, isMainThread, parentPort, workerData,
} = require('node:worker_threads');
if (isMainThread) {
module.exports = function parseJSAsync(script) {
return new Promise((resolve, reject) => {
const worker = new Worker(__filename, {
workerData: script,
});
worker.on('message', resolve);
worker.on('error', reject);
worker.on('exit', (code) => {
if (code !== 0)
reject(new Error(`Worker stopped with exit code ${code}`));
});
});
};
} else {
const { parse } = require('some-js-parsing-library');
const script = workerData;
parentPort.postMessage(parse(script));
}
上面的示例为每个 parseJSAsync()
调用衍生工作线程。在实践中,为这些类型的任务使用工作线程池。否则,创建工作线程的开销可能会超过其收益。
¥The above example spawns a Worker thread for each parseJSAsync()
call. In
practice, use a pool of Workers for these kinds of tasks. Otherwise, the
overhead of creating Workers would likely exceed their benefit.
当实现工作线程池时,使用 AsyncResource
API 通知诊断工具(例如提供异步的堆栈跟踪)有关任务与其结果之间的相关性。有关示例实现,请参阅 async_hooks
文档中的 “将 AsyncResource
用于 Worker
线程池”。
¥When implementing a worker pool, use the AsyncResource
API to inform
diagnostic tools (e.g. to provide asynchronous stack traces) about the
correlation between tasks and their outcomes. See
"Using AsyncResource
for a Worker
thread pool"
in the async_hooks
documentation for an example implementation.
默认情况下,工作线程继承非进程特定的选项。参考 Worker constructor options
了解如何自定义工作线程选项,特别是 argv
和 execArgv
选项。
¥Worker threads inherit non-process-specific options by default. Refer to
Worker constructor options
to know how to customize worker thread options,
specifically argv
and execArgv
options.
worker.getEnvironmentData(key)
#
-
key
<any> 任何可以用作 <Map> 键的任意、可克隆的 JavaScript 值。¥
key
<any> Any arbitrary, cloneable JavaScript value that can be used as a <Map> key. -
返回:<any>
¥Returns: <any>
在工作线程中,worker.getEnvironmentData()
返回传给衍生线程的 worker.setEnvironmentData()
的数据的克隆。每个新的 Worker
都会自动接收到自己的环境数据的副本。
¥Within a worker thread, worker.getEnvironmentData()
returns a clone
of data passed to the spawning thread's worker.setEnvironmentData()
.
Every new Worker
receives its own copy of the environment data
automatically.
const {
Worker,
isMainThread,
setEnvironmentData,
getEnvironmentData,
} = require('node:worker_threads');
if (isMainThread) {
setEnvironmentData('Hello', 'World!');
const worker = new Worker(__filename);
} else {
console.log(getEnvironmentData('Hello')); // Prints 'World!'.
}
worker.isMainThread
#
如果此代码不在 Worker
线程内运行,则为 true
。
¥Is true
if this code is not running inside of a Worker
thread.
const { Worker, isMainThread } = require('node:worker_threads');
if (isMainThread) {
// This re-loads the current file inside a Worker instance.
new Worker(__filename);
} else {
console.log('Inside Worker!');
console.log(isMainThread); // Prints 'false'.
}
worker.markAsUntransferable(object)
#
将对象标记为不可传输。如果 object
出现在 port.postMessage()
调用的传输列表中,则会抛出错误。如果 object
是原始值,则这是一个无操作。
¥Mark an object as not transferable. If object
occurs in the transfer list of
a port.postMessage()
call, an error is thrown. This is a no-op if
object
is a primitive value.
特别是,这对于可以克隆而不是传输的对象,以及被发送方的其他对象使用的对象来说是有意义的。例如,Node.js 将 ArrayBuffer
用于 Buffer
池 标记。
¥In particular, this makes sense for objects that can be cloned, rather than
transferred, and which are used by other objects on the sending side.
For example, Node.js marks the ArrayBuffer
s it uses for its
Buffer
pool with this.
此操作无法撤消。
¥This operation cannot be undone.
const { MessageChannel, markAsUntransferable } = require('node:worker_threads');
const pooledBuffer = new ArrayBuffer(8);
const typedArray1 = new Uint8Array(pooledBuffer);
const typedArray2 = new Float64Array(pooledBuffer);
markAsUntransferable(pooledBuffer);
const { port1 } = new MessageChannel();
try {
// This will throw an error, because pooledBuffer is not transferable.
port1.postMessage(typedArray1, [ typedArray1.buffer ]);
} catch (error) {
// error.name === 'DataCloneError'
}
// The following line prints the contents of typedArray1 -- it still owns
// its memory and has not been transferred. Without
// `markAsUntransferable()`, this would print an empty Uint8Array and the
// postMessage call would have succeeded.
// typedArray2 is intact as well.
console.log(typedArray1);
console.log(typedArray2);
浏览器中没有与此 API 等效的 API。
¥There is no equivalent to this API in browsers.
worker.isMarkedAsUntransferable(object)
#
检查对象是否被标记为不可使用 markAsUntransferable()
转移。
¥Check if an object is marked as not transferable with
markAsUntransferable()
.
const { markAsUntransferable, isMarkedAsUntransferable } = require('node:worker_threads');
const pooledBuffer = new ArrayBuffer(8);
markAsUntransferable(pooledBuffer);
isMarkedAsUntransferable(pooledBuffer); // Returns true.
浏览器中没有与此 API 等效的 API。
¥There is no equivalent to this API in browsers.
worker.markAsUncloneable(object)
#
将对象标记为不可克隆。如果在 port.postMessage()
调用中将 object
用作 message
,则会引发错误。如果 object
是原始值,则这是一个无操作。
¥Mark an object as not cloneable. If object
is used as message
in
a port.postMessage()
call, an error is thrown. This is a no-op if object
is a
primitive value.
这对 ArrayBuffer
或任何类似 Buffer
的对象没有影响。
¥This has no effect on ArrayBuffer
, or any Buffer
like objects.
此操作无法撤消。
¥This operation cannot be undone.
const { markAsUncloneable } = require('node:worker_threads');
const anyObject = { foo: 'bar' };
markAsUncloneable(anyObject);
const { port1 } = new MessageChannel();
try {
// This will throw an error, because anyObject is not cloneable.
port1.postMessage(anyObject)
} catch (error) {
// error.name === 'DataCloneError'
}
浏览器中没有与此 API 等效的 API。
¥There is no equivalent to this API in browsers.
worker.moveMessagePortToContext(port, contextifiedSandbox)
#
-
port
<MessagePort> 要传输的消息端口。¥
port
<MessagePort> The message port to transfer. -
contextifiedSandbox
<Object>vm.createContext()
方法返回的 contextified 对象。¥
contextifiedSandbox
<Object> A contextified object as returned by thevm.createContext()
method. -
¥Returns: <MessagePort>
将 MessagePort
传输到不同的 vm
上下文原始的 port
对象变得不可用,返回的 MessagePort
实例取而代之。
¥Transfer a MessagePort
to a different vm
Context. The original port
object is rendered unusable, and the returned MessagePort
instance
takes its place.
返回的 MessagePort
是目标上下文中的对象,并且继承自其全局的 Object
类。传给 port.onmessage()
监听器的对象也在目标上下文中创建并且从其全局的 Object
类继承。
¥The returned MessagePort
is an object in the target context and
inherits from its global Object
class. Objects passed to the
port.onmessage()
listener are also created in the target context
and inherit from its global Object
class.
但是,创建的 MessagePort
不再继承 EventTarget
,只有 port.onmessage()
可以使用它来接收事件。
¥However, the created MessagePort
no longer inherits from
EventTarget
, and only port.onmessage()
can be used to receive
events using it.
worker.parentPort
#
如果此线程是 Worker
,则这是允许与父线程通信的 MessagePort
。使用 parentPort.postMessage()
发送的消息在使用 worker.on('message')
的父线程中可用,使用 worker.postMessage()
从父线程发送的消息在使用 parentPort.on('message')
的该线程中可用。
¥If this thread is a Worker
, this is a MessagePort
allowing communication with the parent thread. Messages sent using
parentPort.postMessage()
are available in the parent thread
using worker.on('message')
, and messages sent from the parent thread
using worker.postMessage()
are available in this thread using
parentPort.on('message')
.
const { Worker, isMainThread, parentPort } = require('node:worker_threads');
if (isMainThread) {
const worker = new Worker(__filename);
worker.once('message', (message) => {
console.log(message); // Prints 'Hello, world!'.
});
worker.postMessage('Hello, world!');
} else {
// When a message from the parent thread is received, send it back:
parentPort.once('message', (message) => {
parentPort.postMessage(message);
});
}
worker.postMessageToThread(threadId, value[, transferList][, timeout])
#
¥Stability: 1.1 - Active development
-
threadId
<number> 目标线程 ID。如果线程 ID 无效,则将抛出ERR_WORKER_MESSAGING_FAILED
错误。如果目标线程 ID 是当前线程 ID,则将抛出ERR_WORKER_MESSAGING_SAME_THREAD
错误。¥
threadId
<number> The target thread ID. If the thread ID is invalid, aERR_WORKER_MESSAGING_FAILED
error will be thrown. If the target thread ID is the current thread ID, aERR_WORKER_MESSAGING_SAME_THREAD
error will be thrown. -
value
<any> 要发送的值。¥
value
<any> The value to send. -
transferList
<Object[]> 如果在value
中传入一个或多个类似MessagePort
的对象,则这些条目需要transferList
或抛出ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST
。有关详细信息,请参阅port.postMessage()
。¥
transferList
<Object[]> If one or moreMessagePort
-like objects are passed invalue
, atransferList
is required for those items orERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST
is thrown. Seeport.postMessage()
for more information. -
timeout
<number> 等待消息传递的时间(以毫秒为单位)。默认情况下是undefined
,这意味着永远等待。如果操作超时,则抛出ERR_WORKER_MESSAGING_TIMEOUT
错误。¥
timeout
<number> Time to wait for the message to be delivered in milliseconds. By default it'sundefined
, which means wait forever. If the operation times out, aERR_WORKER_MESSAGING_TIMEOUT
error is thrown. -
返回:<Promise> 如果目标线程成功处理了消息,则实现 promise。
¥Returns: <Promise> A promise which is fulfilled if the message was successfully processed by destination thread.
将值发送给另一个由其线程 ID 标识的工作程序。
¥Sends a value to another worker, identified by its thread ID.
如果目标线程没有 workerMessage
事件的监听器,则操作将抛出 ERR_WORKER_MESSAGING_FAILED
错误。
¥If the target thread has no listener for the workerMessage
event, then the operation will throw
a ERR_WORKER_MESSAGING_FAILED
error.
如果目标线程在处理 workerMessage
事件时抛出错误,则操作将抛出 ERR_WORKER_MESSAGING_ERRORED
错误。
¥If the target thread threw an error while processing the workerMessage
event, then the operation will throw
a ERR_WORKER_MESSAGING_ERRORED
error.
当目标线程不是当前线程的直接父线程或子线程时,应使用此方法。如果两个线程是父子线程,则使用 require('node:worker_threads').parentPort.postMessage()
和 worker.postMessage()
让线程进行通信。
¥This method should be used when the target thread is not the direct
parent or child of the current thread.
If the two threads are parent-children, use the require('node:worker_threads').parentPort.postMessage()
and the worker.postMessage()
to let the threads communicate.
以下示例显示了 postMessageToThread
的用法:它创建了 10 个嵌套线程,最后一个将尝试与主线程通信。
¥The example below shows the use of of postMessageToThread
: it creates 10 nested threads,
the last one will try to communicate with the main thread.
import { fileURLToPath } from 'node:url';
import process from 'node:process';
import {
postMessageToThread,
threadId,
workerData,
Worker,
} from 'node:worker_threads';
const channel = new BroadcastChannel('sync');
const level = workerData?.level ?? 0;
if (level < 10) {
const worker = new Worker(fileURLToPath(import.meta.url), {
workerData: { level: level + 1 },
});
}
if (level === 0) {
process.on('workerMessage', (value, source) => {
console.log(`${source} -> ${threadId}:`, value);
postMessageToThread(source, { message: 'pong' });
});
} else if (level === 10) {
process.on('workerMessage', (value, source) => {
console.log(`${source} -> ${threadId}:`, value);
channel.postMessage('done');
channel.close();
});
await postMessageToThread(0, { message: 'ping' });
}
channel.onmessage = channel.close;
const {
postMessageToThread,
threadId,
workerData,
Worker,
} = require('node:worker_threads');
const channel = new BroadcastChannel('sync');
const level = workerData?.level ?? 0;
if (level < 10) {
const worker = new Worker(__filename, {
workerData: { level: level + 1 },
});
}
if (level === 0) {
process.on('workerMessage', (value, source) => {
console.log(`${source} -> ${threadId}:`, value);
postMessageToThread(source, { message: 'pong' });
});
} else if (level === 10) {
process.on('workerMessage', (value, source) => {
console.log(`${source} -> ${threadId}:`, value);
channel.postMessage('done');
channel.close();
});
postMessageToThread(0, { message: 'ping' });
}
channel.onmessage = channel.close;
worker.receiveMessageOnPort(port)
#
-
port
<MessagePort> | <BroadcastChannel> -
返回:<Object> | <undefined>
¥Returns: <Object> | <undefined>
从给定的 MessagePort
接收消息。如果没有消息可用,则返回 undefined
,否则返回具有单个 message
属性的对象,该对象包含消息负载,对应于 MessagePort
队列中最旧的消息。
¥Receive a single message from a given MessagePort
. If no message is available,
undefined
is returned, otherwise an object with a single message
property
that contains the message payload, corresponding to the oldest message in the
MessagePort
's queue.
const { MessageChannel, receiveMessageOnPort } = require('node:worker_threads');
const { port1, port2 } = new MessageChannel();
port1.postMessage({ hello: 'world' });
console.log(receiveMessageOnPort(port2));
// Prints: { message: { hello: 'world' } }
console.log(receiveMessageOnPort(port2));
// Prints: undefined
当使用此函数时,不会触发 'message'
事件,也不会调用 onmessage
监听器。
¥When this function is used, no 'message'
event is emitted and the
onmessage
listener is not invoked.
worker.resourceLimits
#
在这个工作线程中提供了一组 JS 引擎资源约束。如果将 resourceLimits
选项传给 Worker
构造函数,则这与其值匹配。
¥Provides the set of JS engine resource constraints inside this Worker thread.
If the resourceLimits
option was passed to the Worker
constructor,
this matches its values.
如果在主线程中使用此,则其值为空对象。
¥If this is used in the main thread, its value is an empty object.
worker.SHARE_ENV
#
可以作为 Worker
构造函数的 env
选项传入的特殊值,表示当前线程和工作线程应该共享对同一组环境变量的读写访问。
¥A special value that can be passed as the env
option of the Worker
constructor, to indicate that the current thread and the Worker thread should
share read and write access to the same set of environment variables.
const { Worker, SHARE_ENV } = require('node:worker_threads');
new Worker('process.env.SET_IN_WORKER = "foo"', { eval: true, env: SHARE_ENV })
.on('exit', () => {
console.log(process.env.SET_IN_WORKER); // Prints 'foo'.
});
worker.setEnvironmentData(key[, value])
#
-
key
<any> 任何可以用作 <Map> 键的任意、可克隆的 JavaScript 值。¥
key
<any> Any arbitrary, cloneable JavaScript value that can be used as a <Map> key. -
value
<any> 任何任意的、可克隆的 JavaScript 值都将被克隆并自动传给所有新的Worker
实例。如果value
作为undefined
传入,则key
之前设置的任何值都将被删除。¥
value
<any> Any arbitrary, cloneable JavaScript value that will be cloned and passed automatically to all newWorker
instances. Ifvalue
is passed asundefined
, any previously set value for thekey
will be deleted.
worker.setEnvironmentData()
API 设置当前线程中 worker.getEnvironmentData()
的内容以及从当前上下文产生的所有新 Worker
实例。
¥The worker.setEnvironmentData()
API sets the content of
worker.getEnvironmentData()
in the current thread and all new Worker
instances spawned from the current context.
worker.threadId
#
当前线程的整数标识符。在对应的工作线程对象上(如果有的话),可以作为 worker.threadId
使用。此值对于单个进程中的每个 Worker
实例都是唯一的。
¥An integer identifier for the current thread. On the corresponding worker object
(if there is any), it is available as worker.threadId
.
This value is unique for each Worker
instance inside a single process.
worker.workerData
#
任意的 JavaScript 值,其中包含传给该线程的 Worker
构造函数的数据的克隆。
¥An arbitrary JavaScript value that contains a clone of the data passed
to this thread's Worker
constructor.
根据 HTML 结构化克隆算法,数据被克隆,就像使用 postMessage()
一样。
¥The data is cloned as if using postMessage()
,
according to the HTML structured clone algorithm.
const { Worker, isMainThread, workerData } = require('node:worker_threads');
if (isMainThread) {
const worker = new Worker(__filename, { workerData: 'Hello, world!' });
} else {
console.log(workerData); // Prints 'Hello, world!'.
}
类:BroadcastChannel extends EventTarget
#
¥Class: BroadcastChannel extends EventTarget
BroadcastChannel
的实例允许与绑定到相同通道名称的所有其他 BroadcastChannel
实例进行异步的一对多通信。
¥Instances of BroadcastChannel
allow asynchronous one-to-many communication
with all other BroadcastChannel
instances bound to the same channel name.
'use strict';
const {
isMainThread,
BroadcastChannel,
Worker,
} = require('node:worker_threads');
const bc = new BroadcastChannel('hello');
if (isMainThread) {
let c = 0;
bc.onmessage = (event) => {
console.log(event.data);
if (++c === 10) bc.close();
};
for (let n = 0; n < 10; n++)
new Worker(__filename);
} else {
bc.postMessage('hello from every worker');
bc.close();
}
new BroadcastChannel(name)
#
-
name
<any> 要连接的通道名称。任何可以使用${name}
转换为字符串的 JavaScript 值都是允许的。¥
name
<any> The name of the channel to connect to. Any JavaScript value that can be converted to a string using`${name}`
is permitted.
broadcastChannel.close()
#
关闭 BroadcastChannel
连接。
¥Closes the BroadcastChannel
connection.
broadcastChannel.onmessage
#
-
类型:<Function> 当接收到消息时,使用单个
MessageEvent
参数调用。¥Type: <Function> Invoked with a single
MessageEvent
argument when a message is received.
broadcastChannel.onmessageerror
#
-
类型:<Function> 使用接收到的消息调用不能反序列化。
¥Type: <Function> Invoked with a received message cannot be deserialized.
broadcastChannel.postMessage(message)
#
broadcastChannel.ref()
#
unref()
的相反。如果它是唯一剩下的活动句柄(默认行为),则在先前 unref()
BroadcastChannel 上调用 ref()
不会让程序退出。如果端口是 ref()
的,则再次调用 ref()
没有效果。
¥Opposite of unref()
. Calling ref()
on a previously unref()
ed
BroadcastChannel does not let the program exit if it's the only active handle
left (the default behavior). If the port is ref()
ed, calling ref()
again
has no effect.
broadcastChannel.unref()
#
如果这是事件系统中唯一的活动句柄,则在广播通道上调用 unref()
允许线程退出。如果广播通道已经 unref()
,则再次调用 unref()
无效。
¥Calling unref()
on a BroadcastChannel allows the thread to exit if this
is the only active handle in the event system. If the BroadcastChannel is
already unref()
ed calling unref()
again has no effect.
类:MessageChannel
#
¥Class: MessageChannel
worker.MessageChannel
类的实例代表异步的双向通信通道。MessageChannel
没有自己的方法。new MessageChannel()
产生具有 port1
和 port2
属性的对象,其引用链接的 MessagePort
实例。
¥Instances of the worker.MessageChannel
class represent an asynchronous,
two-way communications channel.
The MessageChannel
has no methods of its own. new MessageChannel()
yields an object with port1
and port2
properties, which refer to linked
MessagePort
instances.
const { MessageChannel } = require('node:worker_threads');
const { port1, port2 } = new MessageChannel();
port1.on('message', (message) => console.log('received', message));
port2.postMessage({ foo: 'bar' });
// Prints: received { foo: 'bar' } from the `port1.on('message')` listener
类:MessagePort
#
¥Class: MessagePort
-
¥Extends: <EventTarget>
worker.MessagePort
类的实例代表异步双向通信通道的一端。它可以用来在不同的 Worker
之间传输结构化数据、内存区域和其他 MessagePort
。
¥Instances of the worker.MessagePort
class represent one end of an
asynchronous, two-way communications channel. It can be used to transfer
structured data, memory regions and other MessagePort
s between different
Worker
s.
此实现匹配 浏览器 MessagePort
。
¥This implementation matches browser MessagePort
s.
事件:'close'
#
¥Event: 'close'
一旦通道的任一侧断开连接,则会触发 'close'
事件。
¥The 'close'
event is emitted once either side of the channel has been
disconnected.
const { MessageChannel } = require('node:worker_threads');
const { port1, port2 } = new MessageChannel();
// Prints:
// foobar
// closed!
port2.on('message', (message) => console.log(message));
port2.on('close', () => console.log('closed!'));
port1.postMessage('foobar');
port1.close();
事件:'message'
#
¥Event: 'message'
为任何传入消息触发 'message'
事件,其中包含 port.postMessage()
的克隆输入。
¥The 'message'
event is emitted for any incoming message, containing the cloned
input of port.postMessage()
.
此事件的监听器接收传给 postMessage()
的 value
参数的副本,没有其他参数。
¥Listeners on this event receive a clone of the value
parameter as passed
to postMessage()
and no further arguments.
事件:'messageerror'
#
¥Event: 'messageerror'
当反序列化消息失败时,则会触发 'messageerror'
事件。
¥The 'messageerror'
event is emitted when deserializing a message failed.
目前,当在接收端实例化已发布的 JS 对象时发生错误时,则会触发此事件。这种情况很少见,但可能会发生,例如,当某些 Node.js API 对象在 vm.Context
中接收到时(Node.js API 当前不可用)。
¥Currently, this event is emitted when there is an error occurring while
instantiating the posted JS object on the receiving end. Such situations
are rare, but can happen, for instance, when certain Node.js API objects
are received in a vm.Context
(where Node.js APIs are currently
unavailable).
port.close()
#
禁止在连接的任一端进一步发送消息。当此 MessagePort
上不会发生进一步的通信时,可以调用此方法。
¥Disables further sending of messages on either side of the connection.
This method can be called when no further communication will happen over this
MessagePort
.
'close'
事件 在作为通道一部分的两个 MessagePort
实例上触发。
¥The 'close'
event is emitted on both MessagePort
instances that
are part of the channel.
port.postMessage(value[, transferList])
#
-
value
<any> -
transferList
<Object[]>
向该通道的接收端发送 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:
-
value
可能包含循环引用。¥
value
may contain circular references. -
value
可能包含内置 JS 类型的实例,例如RegExp
、BigInt
、Map
、Set
等。¥
value
may contain instances of builtin JS types such asRegExp
s,BigInt
s,Map
s,Set
s, etc. -
value
可能包含类型化数组,同时使用ArrayBuffer
和SharedArrayBuffer
。¥
value
may contain typed arrays, both usingArrayBuffer
s andSharedArrayBuffer
s. -
value
可能包含WebAssembly.Module
实例。¥
value
may containWebAssembly.Module
instances. -
value
可能不包含原生 (C++ 支持) 对象,除了:¥
value
may not contain native (C++-backed) objects other than:
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
中)。与 子进程 不同,目前不支持传输句柄,例如网络套接字。
¥transferList
may be a list of ArrayBuffer
, MessagePort
, and
FileHandle
objects.
After transferring, they are not 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.
如果 value
包含 SharedArrayBuffer
实例,则可以从任一线程访问它们。它们不能在 transferList
中列出。
¥If value
contains SharedArrayBuffer
instances, those are accessible
from either thread. They cannot be listed in transferList
.
value
可能仍然包含不在 transferList
中的 ArrayBuffer
个实例;在这种情况下,底层内存被复制而不是移动。
¥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('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.
传输 TypedArray 和缓冲区时的注意事项#
¥Considerations when transferring TypedArrays and Buffers
所有 TypedArray
和 Buffer
实例都是对底层 ArrayBuffer
的视图。也就是说,实际存储原始数据的是 ArrayBuffer
,而 TypedArray
和 Buffer
对象提供了查看和操作数据的方式。在同一个 ArrayBuffer
实例上创建多个视图是可能且常见的。使用传输列表传输 ArrayBuffer
时必须非常小心,因为这样做会导致共享同一个 ArrayBuffer
的所有 TypedArray
和 Buffer
实例变得不可用。
¥All TypedArray
and Buffer
instances are views over an underlying
ArrayBuffer
. That is, it is the ArrayBuffer
that actually stores
the raw data while the TypedArray
and Buffer
objects provide a
way of viewing and manipulating the data. It is possible and common
for multiple views to be created over the same ArrayBuffer
instance.
Great care must be taken when using a transfer list to transfer an
ArrayBuffer
as doing so causes all TypedArray
and Buffer
instances that share that same ArrayBuffer
to become unusable.
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
是否可以被传输或克隆完全取决于实例是如何创建的,这通常无法可靠地确定。
¥For Buffer
instances, specifically, whether the underlying
ArrayBuffer
can be transferred or cloned depends entirely on how
instances were created, which often cannot be reliably determined.
ArrayBuffer
可以用 markAsUntransferable()
标记来表示它应该总是被克隆并且永远不会被传输。
¥An ArrayBuffer
can be marked with markAsUntransferable()
to indicate
that it should always be cloned and never transferred.
根据 Buffer
实例的创建方式,它可能拥有也可能不拥有其底层 ArrayBuffer
。除非知道 Buffer
实例拥有它,否则不得传输 ArrayBuffer
。特别是,对于从内部 Buffer
池(例如使用 Buffer.from()
或 Buffer.allocUnsafe()
)创建的 Buffer
,传输它们是不可能的,它们总是被克隆,这会发送整个 Buffer
池的副本。此行为可能会带来意想不到的更高内存使用率和可能的安全问题。
¥Depending on how a Buffer
instance was created, it may or may
not own its underlying ArrayBuffer
. An ArrayBuffer
must not
be transferred unless it is known that the Buffer
instance
owns it. In particular, for Buffer
s created from the internal
Buffer
pool (using, for instance Buffer.from()
or Buffer.allocUnsafe()
),
transferring them is not possible and they are always cloned,
which sends a copy of the entire Buffer
pool.
This behavior may come with unintended higher memory
usage and possible security concerns.
有关 Buffer
池化的更多详细信息,请参阅 Buffer.allocUnsafe()
。
¥See Buffer.allocUnsafe()
for more details on Buffer
pooling.
使用 Buffer.alloc()
或 Buffer.allocUnsafeSlow()
创建的 Buffer
实例的 ArrayBuffer
始终可以传输,但这样做会使这些 ArrayBuffer
的所有其他现有视图不可用。
¥The ArrayBuffer
s for Buffer
instances created using
Buffer.alloc()
or Buffer.allocUnsafeSlow()
can always be
transferred but doing so renders all other existing views of
those ArrayBuffer
s unusable.
使用原型、类、以及访问器克隆对象时的注意事项#
¥Considerations when cloning objects with prototypes, classes, and accessors
因为对象克隆使用 HTML 结构化克隆算法,所以不保留不可枚举的属性、属性访问器和对象原型。特别是,Buffer
对象在接收方将被读取为纯 Uint8Array
,而 JavaScript 类的实例将被克隆为纯 JavaScript 对象。
¥Because object cloning uses the HTML 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, and instances of JavaScript
classes will be cloned as plain JavaScript objects.
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
对象:
¥This limitation extends to many built-in objects, such as the global URL
object:
const { port1, port2 } = new MessageChannel();
port1.onmessage = ({ data }) => console.log(data);
port2.postMessage(new URL('https://example.org'));
// Prints: { }
port.hasRef()
#
¥Stability: 1 - Experimental
如果为 true,则 MessagePort
对象将使 Node.js 事件循环保持活动状态。
¥If true, the MessagePort
object will keep the Node.js event loop active.
port.ref()
#
unref()
的相反。如果它是唯一剩下的活动句柄(默认行为),则在以前的 unref()
端口上调用 ref()
不会让程序退出。如果端口是 ref()
的,则再次调用 ref()
没有效果。
¥Opposite of unref()
. Calling ref()
on a previously unref()
ed port does
not let the program exit if it's the only active handle left (the default
behavior). If the port is ref()
ed, calling ref()
again has no effect.
如果使用 .on('message')
绑定或删除监听器,则根据事件的监听器是否存在,端口将自动进行 ref()
和 unref()
。
¥If listeners are attached or removed using .on('message')
, the port
is ref()
ed and unref()
ed automatically depending on whether
listeners for the event exist.
port.start()
#
开始在此 MessagePort
上接收消息。当将此端口用作事件触发器时,一旦绑定了 'message'
监听器,则会自动调用它
¥Starts receiving messages on this MessagePort
. When using this port
as an event emitter, this is called automatically once 'message'
listeners are attached.
此方法与 Web MessagePort
API 相同。在 Node.js 中,只有在没有事件监听器时才用于忽略消息。Node.js 在处理 .onmessage
方面也有分歧。设置它会自动调用 .start()
,但取消设置它会让消息排队,直到设置新的处理程序或端口被丢弃。
¥This method exists for parity with the Web MessagePort
API. In Node.js,
it is only useful for ignoring messages when no event listener is present.
Node.js also diverges in its handling of .onmessage
. Setting it
automatically calls .start()
, but unsetting it lets messages queue up
until a new handler is set or the port is discarded.
port.unref()
#
如果这是事件系统中唯一的活动句柄,则在端口上调用 unref()
允许线程退出。如果端口已经 unref()
,则再次调用 unref()
无效。
¥Calling unref()
on a port allows the thread to exit if this is the only
active handle in the event system. If the port is already unref()
ed calling
unref()
again has no effect.
如果使用 .on('message')
绑定或删除监听器,则根据事件的监听器是否存在,端口将自动进行 ref()
和 unref()
。
¥If listeners are attached or removed using .on('message')
, the port is
ref()
ed and unref()
ed automatically depending on whether
listeners for the event exist.
类:Worker
#
¥Class: Worker
-
¥Extends: <EventEmitter>
Worker
类代表独立的 JavaScript 执行线程。大多数 Node.js API 都可以在其中使用。
¥The Worker
class represents an independent JavaScript execution thread.
Most Node.js APIs are available inside of it.
工作线程环境中的显着差异是:
¥Notable differences inside a Worker environment are:
-
process.stdin
、process.stdout
、process.stderr
流可能被父线程重定向。¥The
process.stdin
,process.stdout
, andprocess.stderr
streams may be redirected by the parent thread. -
require('node:worker_threads').isMainThread
属性被设置为false
。¥The
require('node:worker_threads').isMainThread
property is set tofalse
. -
require('node:worker_threads').parentPort
消息端口可用。¥The
require('node:worker_threads').parentPort
message port is available. -
process.exit()
不会停止整个程序,只是单个线程,且process.abort()
不可用。¥
process.exit()
does not stop the whole program, just the single thread, andprocess.abort()
is not available. -
设置群组或用户标识的
process.chdir()
和process
方法不可用。¥
process.chdir()
andprocess
methods that set group or user ids are not available. -
process.env
是父线程的环境变量的副本,除非另有说明。对副本的更改在其他线程中不可见,且对原生插件不可见(除非将worker.SHARE_ENV
作为env
选项传给Worker
构造函数)。在 Windows 上,与主线程不同,环境变量的副本以区分大小写的方式运行。¥
process.env
is a copy of the parent thread's environment variables, unless otherwise specified. Changes to one copy are not visible in other threads, and are not visible to native add-ons (unlessworker.SHARE_ENV
is passed as theenv
option to theWorker
constructor). On Windows, unlike the main thread, a copy of the environment variables operates in a case-sensitive manner. -
process.title
不能修改。¥
process.title
cannot be modified. -
信号不通过
process.on('...')
传送。¥Signals are not delivered through
process.on('...')
. -
worker.terminate()
被调用时,执行可能在任何时候停止。¥Execution may stop at any point as a result of
worker.terminate()
being invoked. -
来自父进程的进程间通信通道不可访问。
¥IPC channels from parent processes are not accessible.
-
不支持
trace_events
模块。¥The
trace_events
module is not supported. -
如果原生附加组件满足 特定条件,则只能从多个线程加载。
¥Native add-ons can only be loaded from multiple threads if they fulfill certain conditions.
在其他 Worker
中创建 Worker
实例是可能的。
¥Creating Worker
instances inside of other Worker
s is possible.
与 网络工作线程 和 node:cluster
模块 一样,可以通过线程间消息传递实现双向通信。在内部,Worker
有一对内置的 MessagePort
,它们在创建 Worker
时已经相互关联。虽然父端的 MessagePort
对象没有直接暴露,但其功能通过父线程 Worker
对象上的 worker.postMessage()
和 worker.on('message')
事件暴露。
¥Like Web Workers and the node:cluster
module, two-way communication
can be achieved through inter-thread message passing. Internally, a Worker
has
a built-in pair of MessagePort
s that are already associated with each
other when the Worker
is created. While the MessagePort
object on the parent
side is not directly exposed, its functionalities are exposed through
worker.postMessage()
and the worker.on('message')
event
on the Worker
object for the parent thread.
要创建自定义消息通道(鼓励使用默认全局通道,因为它有助于分离关注点),用户可以在任一线程上创建 MessageChannel
对象,并通过预先存在的线程将 MessageChannel
上的 MessagePort
之一传递给另一个线程 通道,例如全局通道。
¥To create custom messaging channels (which is encouraged over using the default
global channel because it facilitates separation of concerns), users can create
a MessageChannel
object on either thread and pass one of the
MessagePort
s on that MessageChannel
to the other thread through a
pre-existing channel, such as the global one.
有关如何传递消息以及可以成功通过线程屏障传输的 JavaScript 值类型的更多信息,请参阅 port.postMessage()
。
¥See port.postMessage()
for more information on how messages are passed,
and what kind of JavaScript values can be successfully transported through
the thread barrier.
const assert = require('node:assert');
const {
Worker, MessageChannel, MessagePort, isMainThread, parentPort,
} = require('node:worker_threads');
if (isMainThread) {
const worker = new Worker(__filename);
const subChannel = new MessageChannel();
worker.postMessage({ hereIsYourPort: subChannel.port1 }, [subChannel.port1]);
subChannel.port2.on('message', (value) => {
console.log('received:', value);
});
} else {
parentPort.once('message', (value) => {
assert(value.hereIsYourPort instanceof MessagePort);
value.hereIsYourPort.postMessage('the worker is sending this');
value.hereIsYourPort.close();
});
}
new Worker(filename[, options])
#
-
filename
<string> | <URL> 工作线程的主脚本或模块的路径。必须是以./
或../
开头的绝对路径或相对路径(即相对于当前工作目录)、或者是使用file:
或data:
协议的 WHATWGURL
对象使用data:
URL 时,将使用 ECMAScript 模块加载器 根据 MIME 类型解释数据。如果options.eval
是true
,则这是包含 JavaScript 代码(而不是路径)的字符串。¥
filename
<string> | <URL> The path to the Worker's main script or module. Must be either an absolute path or a relative path (i.e. relative to the current working directory) starting with./
or../
, or a WHATWGURL
object usingfile:
ordata:
protocol. When using adata:
URL, the data is interpreted based on MIME type using the ECMAScript module loader. Ifoptions.eval
istrue
, this is a string containing JavaScript code rather than a path. -
options
<Object>-
argv
<any[]> 将被字符串化并附加到工作线程中的process.argv
的参数列表。这与workerData
非常相似,但这些值在全局的process.argv
上可用,就好像它们作为 CLI 选项传给脚本一样。¥
argv
<any[]> List of arguments which would be stringified and appended toprocess.argv
in the worker. This is mostly similar to theworkerData
but the values are available on the globalprocess.argv
as if they were passed as CLI options to the script. -
env
<Object> 如果设置,则指定工作线程内process.env
的初始值。worker.SHARE_ENV
作为一个特殊的值,可以用来指定父线程和子线程共享环境变量;在这种情况下,对一个线程的process.env
对象的更改也会影响另一个线程。默认值:process.env
。¥
env
<Object> If set, specifies the initial value ofprocess.env
inside the Worker thread. As a special value,worker.SHARE_ENV
may be used to specify that the parent thread and the child thread should share their environment variables; in that case, changes to one thread'sprocess.env
object affect the other thread as well. Default:process.env
. -
eval
<boolean> 如果true
并且第一个参数是string
,则将构造函数的第一个参数解释为一旦工作线程在线就执行的脚本。¥
eval
<boolean> Iftrue
and the first argument is astring
, interpret the first argument to the constructor as a script that is executed once the worker is online. -
execArgv
<string[]> 传给工作线程的 node CLI 选项的列表。不支持 V8 选项(如--max-old-space-size
)和影响进程的选项(如--title
)。如果设置,则此在工作线程内部作为process.execArgv
提供。默认情况下,选项继承自父线程。¥
execArgv
<string[]> List of node CLI options passed to the worker. V8 options (such as--max-old-space-size
) and options that affect the process (such as--title
) are not supported. If set, this is provided asprocess.execArgv
inside the worker. By default, options are inherited from the parent thread. -
stdin
<boolean> 如果设置为true
,则worker.stdin
提供其内容在工作线程中显示为process.stdin
的可写流。默认情况下,不提供任何数据。¥
stdin
<boolean> If this is set totrue
, thenworker.stdin
provides a writable stream whose contents appear asprocess.stdin
inside the Worker. By default, no data is provided. -
stdout
<boolean> 如果设置为true
,则worker.stdout
不会自动通过管道传输到父线程中的process.stdout
。¥
stdout
<boolean> If this is set totrue
, thenworker.stdout
is not automatically piped through toprocess.stdout
in the parent. -
stderr
<boolean> 如果设置为true
,则worker.stderr
不会自动通过管道传输到父线程中的process.stderr
。¥
stderr
<boolean> If this is set totrue
, thenworker.stderr
is not automatically piped through toprocess.stderr
in the parent. -
workerData
<any> 任何被克隆并作为require('node:worker_threads').workerData
可用的 JavaScript 值。克隆如 HTML 结构化克隆算法 中所述发生,如果无法克隆对象(例如,因为它包含function
),则会抛出错误。¥
workerData
<any> Any JavaScript value that is cloned and made available asrequire('node:worker_threads').workerData
. The cloning occurs as described in the HTML structured clone algorithm, and an error is thrown if the object cannot be cloned (e.g. because it containsfunction
s). -
trackUnmanagedFds
<boolean> 如果设置为true
,则工作线程会跟踪通过fs.open()
和fs.close()
管理的原始文件描述符,并在工作线程退出时关闭它们,类似于网络套接字或通过FileHandle
API 管理的文件描述符等其他资源。所有嵌套的Worker
都会自动继承此选项。默认值:true
。¥
trackUnmanagedFds
<boolean> If this is set totrue
, then the Worker tracks raw file descriptors managed throughfs.open()
andfs.close()
, and closes them when the Worker exits, similar to other resources like network sockets or file descriptors managed through theFileHandle
API. This option is automatically inherited by all nestedWorker
s. Default:true
. -
transferList
<Object[]> 如果在workerData
中传入一个或多个类似MessagePort
的对象,则这些条目需要transferList
或抛出ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST
。有关详细信息,请参阅port.postMessage()
。¥
transferList
<Object[]> If one or moreMessagePort
-like objects are passed inworkerData
, atransferList
is required for those items orERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST
is thrown. Seeport.postMessage()
for more information. -
resourceLimits
<Object> 新的 JS 引擎实例的一组可选资源限制。达到这些限制会导致Worker
实例终止。这些限制只影响 JS 引擎,不影响外部数据,包括没有ArrayBuffer
。即使设置了这些限制,如果遇到全局内存不足的情况,进程仍可能会中止。¥
resourceLimits
<Object> An optional set of resource limits for the new JS engine instance. Reaching these limits leads to termination of theWorker
instance. These limits only affect the JS engine, and no external data, including noArrayBuffer
s. Even if these limits are set, the process may still abort if it encounters a global out-of-memory situation.-
maxOldGenerationSizeMb
<number> 主堆的最大大小 (以 MB 为单位)。如果设置了命令行参数--max-old-space-size
,它将覆盖此设置。¥
maxOldGenerationSizeMb
<number> The maximum size of the main heap in MB. If the command-line argument--max-old-space-size
is set, it overrides this setting. -
maxYoungGenerationSizeMb
<number> 最近创建的对象的最大堆空间大小。如果设置了命令行参数--max-semi-space-size
,它将覆盖此设置。¥
maxYoungGenerationSizeMb
<number> The maximum size of a heap space for recently created objects. If the command-line argument--max-semi-space-size
is set, it overrides this setting. -
codeRangeSizeMb
<number> 用于生成代码的预分配内存范围的大小。¥
codeRangeSizeMb
<number> The size of a pre-allocated memory range used for generated code. -
stackSizeMb
<number> 线程的默认最大堆栈大小。较小的值可能会导致工作线程实例无法使用。默认值:4
。¥
stackSizeMb
<number> The default maximum stack size for the thread. Small values may lead to unusable Worker instances. Default:4
.
-
-
name
<string> 一个可选的name
附加到工作进程标题用于调试/识别目的,使最终标题为[worker ${id}] ${name}
。默认值:''
。¥
name
<string> An optionalname
to be appended to the worker title for debugging/identification purposes, making the final title as[worker ${id}] ${name}
. Default:''
.
-
事件:'error'
#
¥Event: 'error'
err
<Error>
如果工作线程抛出未捕获的异常,则会触发 'error'
事件。在这种情况下,工作线程被终止。
¥The 'error'
event is emitted if the worker thread throws an uncaught
exception. In that case, the worker is terminated.
事件:'exit'
#
¥Event: 'exit'
exitCode
<integer>
一旦工作线程停止,则会触发 'exit'
事件。如果工作线程是通过调用 process.exit()
退出的,则 exitCode
参数就是传入的退出码。如果工作线程被终止,则 exitCode
参数为 1
。
¥The 'exit'
event is emitted once the worker has stopped. If the worker
exited by calling process.exit()
, the exitCode
parameter is the
passed exit code. If the worker was terminated, the exitCode
parameter is
1
.
这是任何 Worker
实例触发的最终事件。
¥This is the final event emitted by any Worker
instance.
事件:'message'
#
¥Event: 'message'
当工作线程调用 require('node:worker_threads').parentPort.postMessage()
时,则会触发 'message'
事件。详情请见 port.on('message')
事件。
¥The 'message'
event is emitted when the worker thread has invoked
require('node:worker_threads').parentPort.postMessage()
.
See the port.on('message')
event for more details.
在 Worker
对象上触发 'exit'
事件 之前,从工作线程发送的所有消息都会触发。
¥All messages sent from the worker thread are emitted before the
'exit'
event is emitted on the Worker
object.
事件:'messageerror'
#
¥Event: 'messageerror'
当反序列化消息失败时,则会触发 'messageerror'
事件。
¥The 'messageerror'
event is emitted when deserializing a message failed.
事件:'online'
#
¥Event: 'online'
当工作线程开始执行 JavaScript 代码时,则会触发 'online'
事件。
¥The 'online'
event is emitted when the worker thread has started executing
JavaScript code.
worker.getHeapSnapshot([options])
#
-
options
<Object>-
exposeInternals
<boolean> 如果为真,则在堆快照中公开内部结构。默认值:false
。¥
exposeInternals
<boolean> If true, expose internals in the heap snapshot. Default:false
. -
exposeNumericValues
<boolean> 如果为真,则在人工字段中公开数值。默认值:false
。¥
exposeNumericValues
<boolean> If true, expose numeric values in artificial fields. Default:false
.
-
-
返回:<Promise> 对包含 V8 堆快照的可读流的 promise
¥Returns: <Promise> A promise for a Readable Stream containing a V8 heap snapshot
返回工作线程当前状态的 V8 快照的可读流。有关详细信息,请参阅 v8.getHeapSnapshot()
。
¥Returns a readable stream for a V8 snapshot of the current state of the Worker.
See v8.getHeapSnapshot()
for more details.
如果工作线程不再运行(这可能发生在触发 'exit'
事件 之前),则返回的 Promise
会立即被拒绝,并出现 ERR_WORKER_NOT_RUNNING
错误。
¥If the Worker thread is no longer running, which may occur before the
'exit'
event is emitted, the returned Promise
is rejected
immediately with an ERR_WORKER_NOT_RUNNING
error.
worker.performance
#
可用于从工作线程实例查询性能信息的对象。类似于 perf_hooks.performance
。
¥An object that can be used to query performance information from a worker
instance. Similar to perf_hooks.performance
.
performance.eventLoopUtilization([utilization1[, utilization2]])
#
-
utilization1
<Object> 上一次调用eventLoopUtilization()
的结果。¥
utilization1
<Object> The result of a previous call toeventLoopUtilization()
. -
utilization2
<Object> 在utilization1
之前调用eventLoopUtilization()
的结果。¥
utilization2
<Object> The result of a previous call toeventLoopUtilization()
prior toutilization1
. -
返回:<Object>
¥Returns: <Object>
与 perf_hooks
eventLoopUtilization()
相同的调用,除了返回 worker 实例的值。
¥The same call as perf_hooks
eventLoopUtilization()
, except the values
of the worker instance are returned.
一个区别是,与主线程不同,工作线程内的引导是在事件循环内完成的。因此,一旦工作线程的脚本开始执行,事件循环的利用率将立即可用。
¥One difference is that, unlike the main thread, bootstrapping within a worker is done within the event loop. So the event loop utilization is immediately available once the worker's script begins execution.
不增加的 idle
时间并不表示工作线程卡在引导中。下面的示例展示了工作线程的整个生命周期从未累积任何 idle
时间,但仍然能够处理消息。
¥An idle
time that does not increase does not indicate that the worker is
stuck in bootstrap. The following examples shows how the worker's entire
lifetime never accumulates any idle
time, but is still be able to process
messages.
const { Worker, isMainThread, parentPort } = require('node:worker_threads');
if (isMainThread) {
const worker = new Worker(__filename);
setInterval(() => {
worker.postMessage('hi');
console.log(worker.performance.eventLoopUtilization());
}, 100).unref();
return;
}
parentPort.on('message', () => console.log('msg')).unref();
(function r(n) {
if (--n < 0) return;
const t = Date.now();
while (Date.now() - t < 300);
setImmediate(r, n);
})(10);
worker 的事件循环利用率仅在 'online'
事件 触发后可用,如果在此之前或 'exit'
事件 之后调用,则所有属性都具有 0
的值。
¥The event loop utilization of a worker is available only after the 'online'
event emitted, and if called before this, or after the 'exit'
event, then all properties have the value of 0
.
worker.postMessage(value[, transferList])
#
-
value
<any> -
transferList
<Object[]>
向通过 require('node:worker_threads').parentPort.on('message')
接收到的工作线程发送消息。有关详细信息,请参阅 port.postMessage()
。
¥Send a message to the worker that is received via
require('node:worker_threads').parentPort.on('message')
.
See port.postMessage()
for more details.
worker.ref()
#
与 unref()
相反,如果它是唯一剩下的活动句柄(默认行为),则在之前 unref()
worker 上调用 ref()
不会让程序退出。如果工作线程是 ref()
的,则再次调用 ref()
没有效果。
¥Opposite of unref()
, calling ref()
on a previously unref()
ed worker does
not let the program exit if it's the only active handle left (the default
behavior). If the worker is ref()
ed, calling ref()
again has
no effect.
worker.resourceLimits
#
为此工作线程提供了一组 JS 引擎资源约束。如果将 resourceLimits
选项传给 Worker
构造函数,则这与其值匹配。
¥Provides the set of JS engine resource constraints for this Worker thread.
If the resourceLimits
option was passed to the Worker
constructor,
this matches its values.
如果工作线程已经停止,则返回值是空对象。
¥If the worker has stopped, the return value is an empty object.
worker.stderr
#
这是包含工作线程内写入 process.stderr
的数据的可读流。如果 stderr: true
没有传给 Worker
构造函数,则数据将通过管道传输到父线程的 process.stderr
流。
¥This is a readable stream which contains data written to process.stderr
inside the worker thread. If stderr: true
was not passed to the
Worker
constructor, then data is piped to the parent thread's
process.stderr
stream.
worker.stdin
#
如果将 stdin: true
传给 Worker
构造函数,则这是可写流。写入此流的数据将在工作线程中作为 process.stdin
可用。
¥If stdin: true
was passed to the Worker
constructor, this is a
writable stream. The data written to this stream will be made available in
the worker thread as process.stdin
.
worker.stdout
#
这是包含工作线程内写入 process.stdout
的数据的可读流。如果 stdout: true
没有传给 Worker
构造函数,则数据将通过管道传输到父线程的 process.stdout
流。
¥This is a readable stream which contains data written to process.stdout
inside the worker thread. If stdout: true
was not passed to the
Worker
constructor, then data is piped to the parent thread's
process.stdout
stream.
worker.terminate()
#
尽快停止工作线程中的所有 JavaScript 执行。返回在触发 'exit'
事件 时完成的退出代码的 Promise。
¥Stop all JavaScript execution in the worker thread as soon as possible.
Returns a Promise for the exit code that is fulfilled when the
'exit'
event is emitted.
worker.threadId
#
引用线程的整数标识符。在工作线程内部,它作为 require('node:worker_threads').threadId
可用。此值对于单个进程中的每个 Worker
实例都是唯一的。
¥An integer identifier for the referenced thread. Inside the worker thread,
it is available as require('node:worker_threads').threadId
.
This value is unique for each Worker
instance inside a single process.
worker.unref()
#
如果这是事件系统中唯一的活动句柄,则在工作线程上调用 unref()
允许线程退出。如果工作线程已经 unref()
,则再次调用 unref()
无效。
¥Calling unref()
on a worker allows the thread to exit if this is the only
active handle in the event system. If the worker is already unref()
ed calling
unref()
again has no effect.
注意事项#
¥Notes
stdio 的同步阻塞#
¥Synchronous blocking of stdio
Worker
利用通过 <MessagePort> 传递的消息来实现与 stdio
的交互。这意味着来自 Worker
的 stdio
输出可能会被接收端的同步代码阻塞,这会阻塞 Node.js 事件循环。
¥Worker
s utilize message passing via <MessagePort> to implement interactions
with stdio
. This means that stdio
output originating from a Worker
can
get blocked by synchronous code on the receiving end that is blocking the
Node.js event loop.
import {
Worker,
isMainThread,
} from 'node:worker_threads';
if (isMainThread) {
new Worker(new URL(import.meta.url));
for (let n = 0; n < 1e10; n++) {
// Looping to simulate work.
}
} else {
// This output will be blocked by the for loop in the main thread.
console.log('foo');
}
'use strict';
const {
Worker,
isMainThread,
} = require('node:worker_threads');
if (isMainThread) {
new Worker(__filename);
for (let n = 0; n < 1e10; n++) {
// Looping to simulate work.
}
} else {
// This output will be blocked by the for loop in the main thread.
console.log('foo');
}
从预加载脚本启动工作线程#
¥Launching worker threads from preload scripts
从预加载脚本(使用 -r
命令行标志加载和运行的脚本)启动工作线程时要小心。除非显式设置了 execArgv
选项,否则新的工作线程会自动从正在运行的进程继承命令行标志,并将预加载与主线程相同的预加载脚本。如果预加载脚本无条件地启动工作线程,则每个衍生的线程都会衍生另一个直到应用崩溃。
¥Take care when launching worker threads from preload scripts (scripts loaded
and run using the -r
command line flag). Unless the execArgv
option is
explicitly set, new Worker threads automatically inherit the command line flags
from the running process and will preload the same preload scripts as the main
thread. If the preload script unconditionally launches a worker thread, every
thread spawned will spawn another until the application crashes.