Worker 类


Worker 类代表独立的 JavaScript 执行线程。 大多数 Node.js API 都可以在其中使用。

工作线程环境中的显着差异是:

可以在其他 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();
  });
}

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:

Creating Worker instances inside of other Workers 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 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.

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.

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();
  });
}