- assert 断言
- async_hooks 异步钩子
- async_hooks/context 异步上下文
- buffer 缓冲区
- C++插件
- C/C++插件(使用 Node-API)
- C++嵌入器
- child_process 子进程
- cluster 集群
- CLI 命令行
- console 控制台
- crypto 加密
- crypto/webcrypto 网络加密
- debugger 调试器
- deprecation 弃用
- dgram 数据报
- diagnostics_channel 诊断通道
- dns 域名服务器
- domain 域
- env 环境变量
- 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 单个可执行应用程序
- sqlite 轻型数据库
- stream 流
- stream/web 网络流
- string_decoder 字符串解码器
- test 测试
- timers 定时器
- tls 安全传输层
- trace_events 跟踪事件
- tty 终端
- url 网址
- util 实用工具
- v8 引擎
- vm 虚拟机
- wasi 网络汇编系统接口
- worker_threads 工作线程
- zlib 压缩
Node.js v25.3.0 文档
- Node.js v25.3.0
-
目录
- 工作线程
worker_threads.getEnvironmentData(key)worker_threads.isInternalThreadworker_threads.isMainThreadworker_threads.markAsUntransferable(object)worker_threads.isMarkedAsUntransferable(object)worker_threads.markAsUncloneable(object)worker_threads.moveMessagePortToContext(port, contextifiedSandbox)worker_threads.parentPortworker_threads.postMessageToThread(threadId, value[, transferList][, timeout])worker_threads.receiveMessageOnPort(port)worker_threads.resourceLimitsworker_threads.SHARE_ENVworker_threads.setEnvironmentData(key[, value])worker_threads.threadIdworker_threads.threadNameworker_threads.workerDataworker_threads.locks- 类:
BroadcastChannel 继承自 EventTarget - 类:
MessageChannel - 类:
MessagePort - 类:
Workernew Worker(filename[, options])- 事件:
'错误' - 事件:
'exit' - 事件:
'message' - 事件:
'messageerror' - 事件:
'online' worker.cpuUsage([prev])worker.getHeapSnapshot([options])worker.getHeapStatistics()worker.performanceworker.postMessage(value[, transferList])worker.ref()worker.resourceLimitsworker.startCpuProfile()worker.startHeapProfile()worker.stderrworker.stdinworker.stdoutworker.terminate()worker.threadIdworker.threadNameworker.unref()worker[Symbol.asyncDispose]()
- 注意事项
- 工作线程
-
导航
- assert 断言
- async_hooks 异步钩子
- async_hooks/context 异步上下文
- buffer 缓冲区
- C++插件
- C/C++插件(使用 Node-API)
- C++嵌入器
- child_process 子进程
- cluster 集群
- CLI 命令行
- console 控制台
- crypto 加密
- crypto/webcrypto 网络加密
- debugger 调试器
- deprecation 弃用
- dgram 数据报
- diagnostics_channel 诊断通道
- dns 域名服务器
- domain 域
- env 环境变量
- 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 单个可执行应用程序
- sqlite 轻型数据库
- stream 流
- stream/web 网络流
- string_decoder 字符串解码器
- test 测试
- timers 定时器
- tls 安全传输层
- trace_events 跟踪事件
- tty 终端
- url 网址
- util 实用工具
- v8 引擎
- vm 虚拟机
- wasi 网络汇编系统接口
- worker_threads 工作线程
- zlib 压缩
- 其他版本
工作线程#>
【Worker threads】
node:worker_threads 模块允许使用并行执行 JavaScript 的线程。要访问它:
【The node:worker_threads module enables the use of threads that execute
JavaScript in parallel. To access it:】
import worker_threads from 'node:worker_threads';'use strict';
const worker_threads = require('node:worker_threads');
Worker(线程)对于执行CPU密集型的JavaScript操作很有用。它们对I/O密集型工作帮助不大。Node.js内置的异步I/O操作比Worker更高效。
【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.】
import {
Worker,
isMainThread,
parentPort,
workerData,
} from 'node:worker_threads';
if (!isMainThread) {
const { parse } = await import('some-js-parsing-library');
const script = workerData;
parentPort.postMessage(parse(script));
}
export default function parseJSAsync(script) {
return new Promise((resolve, reject) => {
const worker = new Worker(new URL(import.meta.url), {
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}`));
});
});
};'use strict';
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() 调用创建了一个 Worker 线程。实际上,对于这类任务应使用 Worker 池。否则,创建 Worker 的开销可能会超过它们带来的收益。
【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 文档中的 为 Worker 线程池使用 AsyncResource。
【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_threads.getEnvironmentData(key)#>
在工作线程中,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.】
import {
Worker,
isMainThread,
setEnvironmentData,
getEnvironmentData,
} from 'node:worker_threads';
if (isMainThread) {
setEnvironmentData('Hello', 'World!');
const worker = new Worker(new URL(import.meta.url));
} else {
console.log(getEnvironmentData('Hello')); // Prints 'World!'.
}'use strict';
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_threads.isInternalThread#>
- 类型:<boolean>
如果此代码在内部 Worker 线程(例如加载器线程)中运行,则为 true。
【Is true if this code is running inside of an internal Worker thread (e.g the loader thread).】
node --experimental-loader ./loader.js main.js
// loader.js
import { isInternalThread } from 'node:worker_threads';
console.log(isInternalThread); // true// loader.js
'use strict';
const { isInternalThread } = require('node:worker_threads');
console.log(isInternalThread); // true
// main.js
import { isInternalThread } from 'node:worker_threads';
console.log(isInternalThread); // false// main.js
'use strict';
const { isInternalThread } = require('node:worker_threads');
console.log(isInternalThread); // false
worker_threads.isMainThread#>
- 类型:<boolean>
如果此代码未在 Worker 线程中运行,则为 true。
【Is true if this code is not running inside of a Worker thread.】
import { Worker, isMainThread } from 'node:worker_threads';
if (isMainThread) {
// This re-loads the current file inside a Worker instance.
new Worker(new URL(import.meta.url));
} else {
console.log('Inside Worker!');
console.log(isMainThread); // Prints 'false'.
}'use strict';
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_threads.markAsUntransferable(object)#>
object<any> 任何任意的 JavaScript 值。
将对象标记为不可转移。如果 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 对其用于 Buffer 泳池 的 ArrayBuffer 就会这样标记。
【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 ArrayBuffers it uses for its
Buffer pool with this.】
此操作无法撤消。
【This operation cannot be undone.】
import { MessageChannel, markAsUntransferable } from '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);'use strict';
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_threads.isMarkedAsUntransferable(object)#>
检查一个物品是否被标记为不可转让,使用 markAsUntransferable()。
【Check if an object is marked as not transferable with
markAsUntransferable().】
import { markAsUntransferable, isMarkedAsUntransferable } from 'node:worker_threads';
const pooledBuffer = new ArrayBuffer(8);
markAsUntransferable(pooledBuffer);
isMarkedAsUntransferable(pooledBuffer); // Returns true.'use strict';
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_threads.markAsUncloneable(object)#>
object<any> 任何任意的 JavaScript 值。
将对象标记为不可克隆。如果在 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.】
import { markAsUncloneable } from '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'
}'use strict';
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_threads.moveMessagePortToContext(port, contextifiedSandbox)#>
port<MessagePort> 要传输的消息端口。contextifiedSandbox<Object> 一个 情境化 对象,由vm.createContext()方法返回。- 返回:<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_threads.parentPort#>
- 类型:<null> | <MessagePort>
如果这个线程是一个 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').】
import { Worker, isMainThread, parentPort } from 'node:worker_threads';
if (isMainThread) {
const worker = new Worker(new URL(import.meta.url));
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);
});
}'use strict';
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_threads.postMessageToThread(threadId, value[, transferList][, timeout])#>
threadId<number> 目标线程 ID。如果线程 ID 无效,将抛出ERR_WORKER_MESSAGING_FAILED错误。如果目标线程 ID 是当前线程 ID,将抛出ERR_WORKER_MESSAGING_SAME_THREAD错误。value<any> 要发送的值。transferList<Object[]> 如果在value中传入一个或多个类似MessagePort的对象,则这些项需要一个transferList,否则会抛出ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST。更多信息请参见port.postMessage()。timeout<number> 等待消息传递的时间,单位为毫秒。默认值为undefined,表示无限等待。如果操作超时,将抛出一个ERR_WORKER_MESSAGING_TIMEOUT错误。- 返回:<Promise> 如果消息被目标线程成功处理,则此 Promise 会被兑现。
将值发送给另一个由其线程 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 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(new URL(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;'use strict';
const process = require('node:process');
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_threads.receiveMessageOnPort(port)#>
port<MessagePort> | <BroadcastChannel>- 返回:<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.】
import { MessageChannel, receiveMessageOnPort } from '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'use strict';
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_threads.resourceLimits#>
- 类型: <Object>
提供此 Worker 线程内的 JS 引擎资源限制集合。如果在 Worker 构造函数中传入了 resourceLimits 选项,则此处与其值相匹配。
【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_threads.SHARE_ENV#>
- 类型: <symbol>
一个特殊的值,可以作为 Worker 构造函数的 env 选项传入,用于指示当前线程和 Worker 线程应共享对同一组环境变量的读写访问权限。
【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.】
import process from 'node:process';
import { Worker, SHARE_ENV } from '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'.
});'use strict';
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_threads.setEnvironmentData(key[, value])#>
key<any> 任何任意的、可克隆的 JavaScript 值,可用作 <Map> 键。value<any> 任何任意的、可克隆的 JavaScript 值,该值将被克隆并自动传递给所有新的Worker实例。如果value传入undefined,则会删除之前为该key设置的任何值。
worker.setEnvironmentData() API 设置当前线程以及从当前上下文生成的所有新 Worker 实例中 worker.getEnvironmentData() 的内容。
【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_threads.threadId#>
- 类型:<integer>
当前线程的整数标识符。在相应的工作对象上(如果存在),它可作为 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_threads.threadName#>
当前线程的字符串标识符,如果线程未运行则为 null。在相应的 worker 对象上(如果有的话),它可作为 worker.threadName 使用。
【A string identifier for the current thread or null if the thread is not running.
On the corresponding worker object (if there is any), it is available as worker.threadName.】
worker_threads.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.】
import { Worker, isMainThread, workerData } from 'node:worker_threads';
if (isMainThread) {
const worker = new Worker(new URL(import.meta.url), { workerData: 'Hello, world!' });
} else {
console.log(workerData); // Prints 'Hello, world!'.
}'use strict';
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!'.
}
worker_threads.locks#>
- LockManager
LockManager 的一个实例,可用于协调对可能在同一进程内多个线程之间共享的资源的访问。该 API 反映了 浏览器 LockManager 的语义
【An instance of a LockManager that can be used to coordinate
access to resources that may be shared across multiple threads within the same
process. The API mirrors the semantics of the
browser LockManager】
类:Lock#>
【Class: Lock】
Lock 接口提供有关已通过 locks.request() 授予的锁的信息
【The Lock interface provides information about a lock that has been granted via
locks.request()】
lock.name#>
锁的名称。
【The name of the lock.】
lock.mode#>
锁的模式。可以是 shared(共享)或 exclusive(独占)。
【The mode of the lock. Either shared or exclusive.】
类:LockManager#>
【Class: LockManager】
LockManager 接口提供了用于请求和检查锁的方法。要获取 LockManager 实例,请使用
【The LockManager interface provides methods for requesting and introspecting
locks. To obtain a LockManager instance use】
import { locks } from 'node:worker_threads';'use strict';
const { locks } = require('node:worker_threads');
此实现与 浏览器 LockManager API 匹配。
【This implementation matches the browser LockManager API.】
locks.request(name[, options], callback)#>
name<string>options<Object>mode<string> 可以是'exclusive'或'shared'。默认值:'exclusive'。ifAvailable<boolean> 如果为true,请求仅在锁未被持有时才会被授予。如果无法授予,将使用null而不是Lock实例调用callback。默认值:false。steal<boolean> 如果为true,则会释放任何具有相同名称的现有锁,并立即授予请求,优先于任何排队的请求。默认值:false。signal<AbortSignal> 可用于中止正在等待(但尚未被授予)的锁请求。
callback<Function> 一旦锁被授予就会被调用(如果ifAvailable为true且锁不可用,则会立即以null调用)。当函数返回时,锁会自动释放,或者—如果函数返回一个 Promise—则在该 Promise 被解决时释放。- 返回值:<Promise> 一旦锁被释放便会解决。
import { locks } from 'node:worker_threads';
await locks.request('my_resource', async (lock) => {
// The lock has been acquired.
});
// The lock has been released here.'use strict';
const { locks } = require('node:worker_threads');
locks.request('my_resource', async (lock) => {
// The lock has been acquired.
}).then(() => {
// The lock has been released here.
});
locks.query()#>
- 返回:<Promise>
使用一个 LockManagerSnapshot 解析,描述当前进程持有和等待的锁。
【Resolves with a LockManagerSnapshot describing the currently held and pending
locks for the current process.】
import { locks } from 'node:worker_threads';
const snapshot = await locks.query();
for (const lock of snapshot.held) {
console.log(`held lock: name ${lock.name}, mode ${lock.mode}`);
}
for (const pending of snapshot.pending) {
console.log(`pending lock: name ${pending.name}, mode ${pending.mode}`);
}'use strict';
const { locks } = require('node:worker_threads');
locks.query().then((snapshot) => {
for (const lock of snapshot.held) {
console.log(`held lock: name ${lock.name}, mode ${lock.mode}`);
}
for (const pending of snapshot.pending) {
console.log(`pending lock: name ${pending.name}, mode ${pending.mode}`);
}
});
类:BroadcastChannel 继承自 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.】
import {
isMainThread,
BroadcastChannel,
Worker,
} from '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(new URL(import.meta.url));
} else {
bc.postMessage('hello from every worker');
bc.close();
}'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 值。
broadcastChannel.close()#>
关闭 BroadcastChannel 连接。
【Closes the BroadcastChannel connection.】
broadcastChannel.onmessage#>
- 类型:<Function> 当收到消息时,使用单个
MessageEvent参数调用。
broadcastChannel.onmessageerror#>
- 类型:<Function> 用收到的消息调用时无法反序列化。
broadcastChannel.postMessage(message)#>
message<any> 任何可克隆的 JavaScript 值。
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()#>
在 BroadcastChannel 上调用 unref() 可以让线程退出,如果这是事件系统中唯一的活动句柄。如果 BroadcastChannel 已经被 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.】
import { MessageChannel } from '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'use strict';
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】
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 MessagePorts between different
Workers.】
此实现与 浏览器 MessagePorts 相匹配。
【This implementation matches browser MessagePorts.】
事件:'close'#>
【Event: 'close'】
一旦通道的任意一方断开连接,就会触发 'close' 事件。
【The 'close' event is emitted once either side of the channel has been
disconnected.】
import { MessageChannel } from '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();'use strict';
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'】
value<any> 传输的值
'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'】
error<Error> 一个错误对象
当反序列化消息失败时,会触发 'messageerror' 事件。
【The 'messageerror' event is emitted when deserializing a message failed.】
目前,当在接收端实例化已发送的 JS 对象时发生错误时,会触发此事件。这种情况很少见,但可能会发生,例如,当在 vm.Context 中接收到某些 Node.js API 对象时(此时 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对象数组[]
将一个 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可能包含内置 JS 类型的实例,例如RegExp、BigInt、Map、Set等。value可能包含类型化数组,这些数组可以使用ArrayBuffer或SharedArrayBuffer。value可能包含WebAssembly.Module个实例。value可能不包含除以下之外的本地(C++ 支撑的)对象:
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);'use strict';
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 中)。与 子进程 不同的是,目前不支持传输网络套接字等句柄。
如果 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 ]);'use strict';
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> | <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(例如使用 Buffer.from() 或 Buffer.allocUnsafe()),无法转移它们,并且它们总是被克隆,这会发送整个 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 Buffers 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 ArrayBuffers for Buffer instances created using
Buffer.alloc() or Buffer.allocUnsafeSlow() can always be
transferred but doing so renders all other existing views of
those ArrayBuffers 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()#>
- 返回:<boolean>
如果为真,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】
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流可能会被父线程重定向。require('node:worker_threads').isMainThread属性被设置为false。require('node:worker_threads').parentPort消息端口可用。process.exit()不会停止整个程序,只会停止单个线程,而且process.abort()不可用。- 设置组或用户 ID 的
process.chdir()和process方法不可用。 process.env是父线程环境变量的副本,除非另有说明。对其中一个副本的更改在其他线程中不可见,也不会被本地插件看到(除非将worker.SHARE_ENV作为env选项传递给Worker构造函数)。在 Windows 上,与主线程不同,环境变量的副本以区分大小写的方式操作。process.title无法修改。- 信号不会通过
process.on('...')传输。 - 由于调用了
worker.terminate(),执行可能在任何时候停止。 - 父进程的 IPC 通道无法访问。
- 不支持
trace_events模块。 - 本地插件只有在满足 某些条件 的情况下才能从多个线程加载。
在另一个 Worker 内部创建 Worker 实例是可能的。
【Creating Worker instances inside of other Workers is possible.】
像 网页工作者 和 node:cluster 模块 一样,通过线程间消息传递可以实现双向通信。在内部,Worker 内置了一对 MessagePort,它们在 Worker 创建时已经相互关联。虽然父线程一侧的 MessagePort 对象不会直接暴露,但其功能通过 worker.postMessage() 和 Worker 对象上的 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 MessagePorts 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
MessagePorts 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.】
import assert from 'node:assert';
import {
Worker, MessageChannel, MessagePort, isMainThread, parentPort,
} from 'node:worker_threads';
if (isMainThread) {
const worker = new Worker(new URL(import.meta.url));
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();
});
}'use strict';
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> Worker 主脚本或模块的路径。必须是绝对路径或相对路径(即相对于当前工作目录),相对路径需以./或../开头,或是使用file:或data:协议的 WHATWGURL对象。使用data:URL 时,数据会根据 MIME 类型通过 ECMAScript 模块加载器 进行解释。如果options.eval为true,则此处为包含 JavaScript 代码的字符串,而不是路径。options<Object>argv<any[]> 参数列表,这些参数将被转换为字符串并追加到工作线程的process.argv中。这与workerData大致相似,但这些值会出现在全局process.argv中,就好像它们作为命令行选项传递给脚本一样。env<Object> 如果设置,指定 Worker 线程内部process.env的初始值。作为一个特殊值,可以使用worker.SHARE_ENV来指定父线程和子线程共享它们的环境变量;在这种情况下,对某一线程的process.env对象的更改也会影响另一线程。默认值:process.env。eval<boolean> 如果为true且第一个参数是string,则将构造函数的第一个参数解释为脚本,在工作线程上线后执行一次。execArgv<string[]> 传递给工作线程的 Node CLI 选项列表。V8 选项(例如--max-old-space-size)以及影响进程的选项(例如--title)不被支持。如果设置,则在工作线程中作为process.execArgv提供。默认情况下,选项会从父线程继承。stdin<boolean> 如果设置为true,则worker.stdin会提供一个可写流,其内容将显示在 Worker 内的process.stdin中。默认情况下,不提供任何数据。stdout<boolean> 如果设置为true,则worker.stdout不会自动传输到父进程的process.stdout。stderr<boolean> 如果设置为true,则worker.stderr不会自动传输到父进程的process.stderr。workerData<any> 任何 JavaScript 值都会被克隆并作为require('node:worker_threads').workerData提供。克隆的过程如 HTML 结构化克隆算法 所述,如果对象无法克隆(例如因为它包含function),则会抛出错误。trackUnmanagedFds<boolean> 如果设置为true,Worker 将跟踪通过fs.open()和fs.close()管理的原始文件描述符,并在 Worker 退出时关闭它们,这类似于通过FileHandleAPI 管理的网络套接字或文件描述符等其他资源。此选项会自动被所有嵌套的Worker继承。默认值:true。transferList<Object[]> 如果在workerData中传入一个或多个类似MessagePort的对象,则必须为这些对象提供transferList,否则会抛出ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST。有关更多信息,请参阅port.postMessage()。resourceLimits<Object> 新的 JS 引擎实例的可选资源限制集合。达到这些限制会导致Worker实例终止。这些限制只影响 JS 引擎,不影响任何外部数据,包括ArrayBuffer。即使设置了这些限制,如果进程遇到全局内存不足的情况,仍可能会中止。maxOldGenerationSizeMb<number> 主堆的最大大小(以 MB 为单位)。如果命令行参数--max-old-space-size已设置,它将覆盖此设置。maxYoungGenerationSizeMb<number> 最近创建对象的堆空间的最大大小。如果命令行参数--max-semi-space-size已设置,它将覆盖此设置。codeRangeSizeMb<number> 用于生成代码的预分配内存范围的大小。stackSizeMb<number> 线程的默认最大堆栈大小。较小的值可能导致 Worker 实例无法使用。默认值:4。
name<string> 一个可选的name,用于替换线程名称以及用于调试/识别目的的工作线程标题,最终标题将为[worker ${id}] ${name}。该参数的最大允许长度取决于操作系统。如果提供的名称超过限制,将会被截断- 最大尺寸:
- Windows:32,767 个字符
- macOS:64 个字符
- Linux:16 个字符
- NetBSD:受限于
PTHREAD_MAX_NAMELEN_NP - FreeBSD 和 OpenBSD:限制为
MAXCOMLEN默认值:'WorkerThread'。
- 最大尺寸:
事件:'错误'#>
【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'】
value<any> 传输的值
'message' 事件在工作线程调用 require('node:worker_threads').parentPort.postMessage() 时触发。有关更多详细信息,请参阅 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'】
error<Error> 一个错误对象
当反序列化消息失败时,会触发 '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.cpuUsage([prev])#>
- 返回:<Promise>
该方法返回一个 Promise,该 Promise 会解析为与 process.threadCpuUsage() 相同的对象,或者如果工作线程不再运行,则会以 ERR_WORKER_NOT_RUNNING 错误拒绝。该方法允许从实际线程外部观察统计信息。
【This method returns a Promise that will resolve to an object identical to process.threadCpuUsage(),
or reject with an ERR_WORKER_NOT_RUNNING error if the worker is no longer running.
This methods allows the statistics to be observed from outside the actual thread.】
worker.getHeapSnapshot([options])#>
返回一个可读流,用于获取当前 Worker 状态的 V8 快照。更多详情请参见 v8.getHeapSnapshot()。
【Returns a readable stream for a V8 snapshot of the current state of the Worker.
See v8.getHeapSnapshot() for more details.】
如果 Worker 线程不再运行,这可能会在 '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.getHeapStatistics()#>
- 返回:<Promise>
该方法返回一个 Promise,该 Promise 会解析为与 v8.getHeapStatistics() 相同的对象,或者如果工作线程不再运行,则会以 ERR_WORKER_NOT_RUNNING 错误拒绝。该方法允许从实际线程外部观察统计信息。
【This method returns a Promise that will resolve to an object identical to v8.getHeapStatistics(),
or reject with an ERR_WORKER_NOT_RUNNING error if the worker is no longer running.
This methods allows the statistics to be observed from outside the actual thread.】
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()的结果。utilization2<Object> 在utilization1之前对eventLoopUtilization()的先前调用的结果。- 返回:<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.】
import { Worker, isMainThread, parentPort } from 'node:worker_threads';
if (isMainThread) {
const worker = new Worker(new URL(import.meta.url));
setInterval(() => {
worker.postMessage('hi');
console.log(worker.performance.eventLoopUtilization());
}, 100).unref();
} else {
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);
}'use strict';
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();
} else {
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);
}
只有在 '在线'事件 发出之后,才能获取工作线程的事件循环利用率,如果在此之前或在 '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对象数组[]
向通过 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() 不会让程序在它是唯一活动句柄时退出(默认行为)。如果 worker 已经是 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#>
- 类型: <Object>
为此 Worker 线程提供 JS 引擎资源限制的集合。如果在 Worker 构造函数中传入了 resourceLimits 选项,则此处与其值相匹配。
【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.startCpuProfile()#>
- 返回:<Promise>
启动 CPU 分析,然后返回一个 Promise,该 Promise 会以错误或 CPUProfileHandle 对象作为结果。此 API 支持 await using 语法。
【Starting a CPU profile then return a Promise that fulfills with an error
or an CPUProfileHandle object. This API supports await using syntax.】
const { Worker } = require('node:worker_threads');
const worker = new Worker(`
const { parentPort } = require('worker_threads');
parentPort.on('message', () => {});
`, { eval: true });
worker.on('online', async () => {
const handle = await worker.startCpuProfile();
const profile = await handle.stop();
console.log(profile);
worker.terminate();
});
await using 示例。
const { Worker } = require('node:worker_threads');
const w = new Worker(`
const { parentPort } = require('node:worker_threads');
parentPort.on('message', () => {});
`, { eval: true });
w.on('online', async () => {
// Stop profile automatically when return and profile will be discarded
await using handle = await w.startCpuProfile();
});
worker.startHeapProfile()#>
- 返回:<Promise>
启动堆分析,然后返回一个 Promise,该 Promise 要么以错误完成,要么返回一个 HeapProfileHandle 对象。此 API 支持 await using 语法。
【Starting a Heap profile then return a Promise that fulfills with an error
or an HeapProfileHandle object. This API supports await using syntax.】
const { Worker } = require('node:worker_threads');
const worker = new Worker(`
const { parentPort } = require('worker_threads');
parentPort.on('message', () => {});
`, { eval: true });
worker.on('online', async () => {
const handle = await worker.startHeapProfile();
const profile = await handle.stop();
console.log(profile);
worker.terminate();
});
await using 示例。
const { Worker } = require('node:worker_threads');
const w = new Worker(`
const { parentPort } = require('node:worker_threads');
parentPort.on('message', () => {});
`, { eval: true });
w.on('online', async () => {
// Stop profile automatically when return and profile will be discarded
await using handle = await w.startHeapProfile();
});
worker.stderr#>
这是一个可读流,它包含写入 process.stderr 的数据,这些数据来自工作线程。如果在 Worker 构造函数中未传递 stderr: true,则数据会被传输到父线程的 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#>
- 类型: <null> | <stream.Writable>
如果在 Worker 构造函数中传递了 stdin: true,则这是一个可写流。写入此流的数据将在工作线程中以 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 的数据。如果在 Worker 构造函数中没有传入 stdout: true,那么数据将被传输到父线程的 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()#>
- 返回:<Promise>
尽快停止工作线程中的所有 JavaScript 执行。返回一个退出代码的 Promise,当 '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#>
- 类型:<integer>
被引用线程的整数标识符。在工作线程内部,它可作为 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.threadName#>
引用线程的字符串标识符,如果线程未运行则为 null。在工作线程内部,它可作为 require('node:worker_threads').threadName 使用。
【A string identifier for the referenced thread or null if the thread is not running.
Inside the worker thread, it is available as require('node:worker_threads').threadName.】
worker.unref()#>
对 worker 调用 unref() 可以使线程在事件系统中这是唯一活动句柄时退出。如果 worker 已经被 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.】
worker[Symbol.asyncDispose]()#>
当退出处置范围时调用 worker.terminate()。
【Calls worker.terminate() when the dispose scope is exited.】
async function example() {
await using worker = new Worker('for (;;) {}', { eval: true });
// Worker is automatically terminate when the scope is exited.
}
注意事项#>
【Notes】
stdio 的同步阻塞#>
【Synchronous blocking of stdio】
Worker 通过 <MessagePort> 使用消息传递来实现与 stdio 的交互。这意味着,来自 Worker 的 stdio 输出可能会被接收端的同步代码阻塞,从而阻塞 Node.js 事件循环。
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.】