Worker 类
- 继承自: <EventEmitter>
Worker
类代表独立的 JavaScript 执行线程。
大多数 Node.js API 都可以在其中使用。
工作线程环境中的显着差异是:
process.stdin
、process.stdout
、process.stderr
流可能被父线程重定向。require('node:worker_threads').isMainThread
属性被设置为false
。require('node:worker_threads').parentPort
消息端口可用。process.exit()
不会停止整个程序,只是单个线程,且process.abort()
不可用。- 设置群组或用户标识的
process.chdir()
和process
方法不可用。 process.env
是父线程的环境变量的副本,除非另有说明。 对副本的更改在其他线程中不可见,且对原生插件不可见(除非将worker.SHARE_ENV
作为env
选项传给Worker
构造函数)。process.title
不能修改。- 信号不通过
process.on('...')
传送。 worker.terminate()
被调用时,执行可能在任何时候停止。- 来自父进程的进程间通信通道不可访问。
- 不支持
trace_events
模块。 - 如果满足某些条件,则原生插件只能从多个线程加载。
可以在其他 Worker
内部创建 Worker
实例。
和网络工作线程和 node:cluster
模块一样,可以通过线程间消息传递来实现双向通信。
在内部,Worker
有一对内置的 MessagePort
,在创建 Worker
时它们已经相互关联。
虽然父端的 MessagePort
对象没有直接暴露,但其功能通过父线程 Worker
对象上的 worker.postMessage()
和 worker.on('message')
事件暴露。
要创建自定义的消息通道(鼓励使用默认的全局通道,因为它有助于分离关注点),用户可以在任一线程上创建 MessageChannel
对象,并通过预先存在的通道(例如全局通道)将该 MessageChannel
上的 MessagePort
之一传给另一个线程。
有关如何传递消息以及可以成功通过线程屏障传输的 JavaScript 值类型的更多信息,请参阅 port.postMessage()
。
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();
});
}
- Extends: <EventEmitter>
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:
- The
process.stdin
,process.stdout
, andprocess.stderr
streams may be redirected by the parent thread. - The
require('node:worker_threads').isMainThread
property is set tofalse
. - The
require('node:worker_threads').parentPort
message port is available. process.exit()
does not stop the whole program, just the single thread, andprocess.abort()
is not available.process.chdir()
andprocess
methods that set group or user ids are not available.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).process.title
cannot be modified.- Signals are not delivered through
process.on('...')
. - Execution may stop at any point as a result of
worker.terminate()
being invoked. - IPC channels from parent processes are not accessible.
- The
trace_events
module is not supported. - Native add-ons can only be loaded from multiple threads if they fulfill certain conditions.
Creating Worker
instances inside of other Worker
s is possible.
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.
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.
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();
});
}