ワーカー スレッド#

安定度: 2 - 安定

ソースコード: lib/worker_threads.js

node:worker_threads モジュールを使用すると、JavaScript を並行して実行するスレッドを使用できます。アクセスするには、

const worker = require('node:worker_threads'); 

ワーカー (スレッド) は、CPU 負荷の高い JavaScript 操作を実行するのに役立ちます。I/O 負荷の高い作業にはあまり役立ちません。Node.js に組み込まれている非同期 I/O 操作の方が、ワーカーよりも効率的です。

child_processcluster とは異なり、worker_threads はメモリを共有できます。これは、ArrayBuffer インスタンスを転送するか、SharedArrayBuffer インスタンスを共有することによって行います。

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() 呼び出しごとにワーカー スレッドを生成します。実際には、これらの種類のタスクにはワーカーのプールを使用します。そうしないと、ワーカーの作成のオーバーヘッドが、それらの利点を上回る可能性が高くなります。

ワーカー プールを実装する場合は、AsyncResource API を使用して、タスクとそれらの結果の相関関係について診断ツール (例: 非同期スタック トレースを提供するため) に通知します。実装例については、async_hooks ドキュメントの 「ワーカー スレッド プールに AsyncResource を使用する」 を参照してください。

ワーカー スレッドは、デフォルトでプロセス固有ではないオプションを継承します。ワーカー スレッドのオプション (特に argv および execArgv オプション) をカスタマイズする方法については、ワーカー コンストラクター オプション を参照してください。

worker.getEnvironmentData(key)#

  • key <any> <Map> キーとして使用できる、任意の複製可能な JavaScript 値。
  • 戻り値: <any>

ワーカー スレッド内では、worker.getEnvironmentData() は、生成スレッドの worker.setEnvironmentData() に渡されたデータのクローンを返します。すべての新しい Worker は、環境データの独自のコピーを自動的に受け取ります。

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 です。

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 <any> 任意の JavaScript 値。

オブジェクトを転送不可としてマークします。objectport.postMessage() 呼び出しの転送リストに出現した場合、エラーがスローされます。object がプリミティブ値の場合は、これは no-op です。

特に、これは、転送ではなく複製でき、送信側で他のオブジェクトによって使用されるオブジェクトに意味があります。たとえば、Node.js は、Buffer プールに使用する ArrayBuffer をこれでマークします。

この操作は元に戻せません。

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 に相当するものはありません。

worker.isMarkedAsUntransferable(object)#

markAsUntransferable() でオブジェクトが転送不可としてマークされているかどうかを確認します。

const { markAsUntransferable, isMarkedAsUntransferable } = require('node:worker_threads');

const pooledBuffer = new ArrayBuffer(8);
markAsUntransferable(pooledBuffer);

isMarkedAsUntransferable(pooledBuffer);  // Returns true. 

ブラウザーにはこの API に相当するものはありません。

worker.moveMessagePortToContext(port, contextifiedSandbox)#

MessagePort を別の vm コンテキストに転送します。元の port オブジェクトは使用できなくなり、返された MessagePort インスタンスがその場所に置き換わります。

返された MessagePort は、ターゲット コンテキストのオブジェクトであり、そのグローバル Object クラスから継承されます。port.onmessage() リスナーに渡されるオブジェクトもターゲット コンテキストで作成され、そのグローバル Object クラスから継承されます。

ただし、作成された MessagePortEventTarget から継承されなくなり、port.onmessage() のみを使用してイベントを受信できます。

worker.parentPort#

このスレッドが Worker の場合、これは親スレッドとの通信を可能にする MessagePort です。parentPort.postMessage() を使用して送信されたメッセージは、worker.on('message') を使用して親スレッドで使用でき、worker.postMessage() を使用して親スレッドから送信されたメッセージは、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.receiveMessageOnPort(port)#

指定された MessagePort から単一のメッセージを受信します。メッセージが利用できない場合は undefined が返され、それ以外の場合は、MessagePort のキュー内の最も古いメッセージに対応する、メッセージ ペイロードを含む単一の message プロパティを持つオブジェクトが返されます。

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 リスナーは呼び出されません。

worker.resourceLimits#

このワーカー スレッド内の JS エンジン リソースの制約のセットを提供します。resourceLimits オプションが Worker コンストラクターに渡された場合、これはその値と一致します。

これがメインスレッドで使用されている場合、その値は空のオブジェクトになります。

worker.SHARE_ENV#

現在のスレッドと Worker スレッドが同じ環境変数のセットへの読み取りおよび書き込みアクセスを共有する必要があることを示すために、Worker コンストラクターの env オプションとして渡すことができる特別な値。

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 値。
  • value <any> クローン可能ないかなる JavaScript 値でも、クローンされてすべての新しい Worker インスタンスに自動的に渡されます。valueundefined として渡された場合、key に以前設定された値は削除されます。

worker.setEnvironmentData() API は、現在のスレッドと現在のコンテキストから生成されたすべての新しい Worker インスタンスの worker.getEnvironmentData() の内容を設定します。

worker.threadId#

現在のスレッドの整数識別子。対応する worker オブジェクト (存在する場合) では、worker.threadId として利用できます。この値は、単一プロセス内の各 Worker インスタンスに対して一意です。

worker.workerData#

このスレッドの Worker コンストラクターに渡されたデータのクローンを含む任意の JavaScript 値。

データは、HTML 構造化クローンアルゴリズムに従って、postMessage() を使用したかのようにクローンされます。

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#

BroadcastChannel のインスタンスを使用すると、同じチャネル名にバインドされた他のすべての BroadcastChannel インスタンスと非同期の一対多通信が可能になります。

'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 接続を閉じます。

broadcastChannel.onmessage#

  • 型: <Function> メッセージを受信すると、単一の MessageEvent 引数で呼び出されます。

broadcastChannel.onmessageerror#

  • 型: <Function> 受信したメッセージをデシリアライズできない場合に呼び出されます。

broadcastChannel.postMessage(message)#

  • message <any> 任意のクローン可能な JavaScript 値。

broadcastChannel.ref()#

unref() の反対。以前に unref() された BroadcastChannel で ref() を呼び出しても、(デフォルトの動作である) 残りのアクティブなハンドルがそれだけの場合、プログラムが終了することはありません。ポートが ref() されている場合、再度 ref() を呼び出しても効果はありません。

broadcastChannel.unref()#

BroadcastChannel で unref() を呼び出すと、イベント システムでこれが唯一のアクティブなハンドルである場合、スレッドを終了できます。BroadcastChannel がすでに unref() されている場合、再度 unref() を呼び出しても効果はありません。

クラス: MessageChannel#

worker.MessageChannel クラスのインスタンスは、非同期の双方向通信チャネルを表します。MessageChannel には独自のメソッドはありません。new MessageChannel() は、リンクされた MessagePort インスタンスを参照する port1 プロパティと port2 プロパティを持つオブジェクトを生成します。

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#

worker.MessagePort クラスのインスタンスは、非同期の双方向通信チャネルの一方の端を表します。これを使用して、構造化データ、メモリ領域、および他の MessagePort を異なる Worker 間で転送できます。

この実装は、ブラウザーの MessagePort と一致します。

イベント: 'close'#

チャネルの両側が切断されると、'close' イベントが 1 回だけ発生します。

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'#

  • value <any> 送信された値

port.postMessage() のクローン化された入力を含む、着信メッセージに対して 'message' イベントが発生します。

このイベントのリスナーは、postMessage() に渡された value パラメーターのクローンを受信し、それ以上の引数はありません。

イベント: 'messageerror'#

  • error <Error> エラー オブジェクト

メッセージのデシリアライズに失敗した場合、'messageerror' イベントが発生します。

現在、このイベントは、受信側でポストされた JS オブジェクトをインスタンス化中にエラーが発生した場合に発生します。このような状況はまれですが、たとえば、特定の Node.js API オブジェクトが vm.Context (現在 Node.js API を利用できない場所) で受信された場合に発生する可能性があります。

port.close()#

接続の両側でのメッセージのそれ以上の送信を無効にします。このメソッドは、この MessagePort を介してそれ以上の通信が発生しない場合に呼び出すことができます。

チャネルの一部である両方の MessagePort インスタンスで、'close' イベントが発生します。

port.postMessage(value[, transferList])#

このチャネルの受信側に JavaScript 値を送信します。value は、HTML 構造化クローン アルゴリズムと互換性のある方法で転送されます。

特に、JSON との重要な違いは次のとおりです。

  • value には循環参照を含めることができます。
  • value には、RegExpBigIntMapSet などの組み込み JS 型のインスタンスを含めることができます。
  • value には、ArrayBufferSharedArrayBuffer の両方を使用した型付き配列を含めることができます。
  • value には、WebAssembly.Module インスタンスを含めることができます。
  • value には、次を除くネイティブ (C++ バックアップ) オブジェクトを含めることはできません。
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 には、ArrayBufferMessagePort、および FileHandle オブジェクトのリストを指定できます。転送後、これらはチャネルの送信側では使用できなくなります (value に含まれていない場合でも)。子プロセスの場合とは異なり、ネットワークソケットなどのハンドルの転送は現在サポートされていません。

valueSharedArrayBuffer インスタンスが含まれている場合、それらはどちらのスレッドからもアクセスできます。これらを transferList に含めることはできません。

value には、transferList に含まれていない ArrayBuffer インスタンスを含めることもできます。その場合、基になるメモリは移動されるのではなくコピーされます。

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 ]); 

メッセージオブジェクトはすぐに複製され、送信後に副作用なしで変更できます。

この API の背後にあるシリアル化およびデシリアル化メカニズムの詳細については、node:v8 モジュールのシリアル化 API を参照してください。

TypedArray と Buffer の転送に関する考慮事項#

すべての TypedArray および Buffer インスタンスは、基になる ArrayBuffer のビューです。つまり、生データを実際に格納するのは ArrayBuffer であり、TypedArray および Buffer オブジェクトはデータの表示および操作方法を提供します。複数のビューを同じ ArrayBuffer インスタンス上に作成することは可能であり、一般的です。転送リストを使用して ArrayBuffer を転送する場合は、細心の注意を払う必要があります。転送すると、同じ ArrayBuffer を共有するすべての TypedArray および Buffer インスタンスが使用できなくなるためです。

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 を転送または複製できるかどうかは、インスタンスがどのように作成されたかに完全に依存し、確実に判断できないことがよくあります。

ArrayBuffermarkAsUntransferable() を使用してマークを付けることで、常に複製され、転送されないように指示できます。

Buffer インスタンスがどのように作成されたかによっては、基になる ArrayBuffer を所有している場合とそうでない場合があります。Buffer インスタンスが所有していることがわかっている場合を除き、ArrayBuffer を転送してはなりません。特に、内部の Buffer プールから作成された (たとえば、Buffer.from() または Buffer.allocUnsafe() を使用) Buffer の場合、それらを転送することはできず、常に複製されます。これにより、Buffer プール全体がコピーされて送信されます。この動作は、意図しないメモリ使用量の増加やセキュリティ上の懸念を引き起こす可能性があります。

Buffer プールに関する詳細については、Buffer.allocUnsafe() を参照してください。

Buffer.alloc() または Buffer.allocUnsafeSlow() を使用して作成された Buffer インスタンスの ArrayBuffer は常に転送できますが、転送すると、それらの ArrayBuffer の他のすべての既存のビューが使用できなくなります。

プロトタイプ、クラス、およびアクセサを持つオブジェクトの複製に関する考慮事項#

オブジェクトの複製では、HTML構造化クローンアルゴリズムが使用されるため、列挙不可のプロパティ、プロパティアクセサ、およびオブジェクトプロトタイプは保持されません。特に、Buffer オブジェクトは、受信側でプレーンな Uint8Array として読み取られ、JavaScript クラスのインスタンスはプレーンな JavaScript オブジェクトとして複製されます。

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 オブジェクトなど、多くの組み込みオブジェクトにまで及びます。

const { port1, port2 } = new MessageChannel();

port1.onmessage = ({ data }) => console.log(data);

port2.postMessage(new URL('https://example.org'));

// Prints: { } 

port.hasRef()#

安定性: 1 - 試験的

true の場合、MessagePort オブジェクトは Node.js イベントループをアクティブな状態に保ちます。

port.ref()#

unref() の反対です。以前に unref() されたポートで ref() を呼び出しても、プログラムが残っている唯一のアクティブなハンドルである場合は終了しません (デフォルトの動作)。ポートが ref() されている場合、再度 ref() を呼び出しても効果はありません。

.on('message') を使用してリスナーがアタッチまたは削除された場合、イベントのリスナーが存在するかどうかに応じて、ポートは自動的に ref() および unref() されます。

port.start()#

この MessagePort でのメッセージの受信を開始します。このポートをイベントエミッターとして使用する場合、'message' リスナーがアタッチされると、これは自動的に呼び出されます。

このメソッドは、Web MessagePort API とのパリティのために存在します。Node.js では、イベントリスナーが存在しない場合にメッセージを無視する場合にのみ役立ちます。Node.js では、.onmessage の処理も異なり、設定すると自動的に .start() が呼び出されますが、設定を解除すると、新しいハンドラが設定されるか、ポートが破棄されるまでメッセージがキューに保持されます。

port.unref()#

ポートで unref() を呼び出すと、イベントシステム内でこれが唯一のアクティブなハンドルである場合に、スレッドを終了できます。ポートがすでに unref() されている場合、再度 unref() を呼び出しても効果はありません。

.on('message') を使用してリスナーがアタッチまたは削除された場合、イベントのリスナーが存在するかどうかに応じて、ポートは自動的に ref() および unref() されます。

クラス: Worker#

Worker クラスは、独立した JavaScript 実行スレッドを表します。ほとんどの Node.js API はその内部で使用できます。

Worker 環境内での重要な違いは次のとおりです。

  • process.stdinprocess.stdout、および process.stderr ストリームは、親スレッドによってリダイレクトされる場合があります。
  • require('node:worker_threads').isMainThread プロパティは false に設定されています。
  • require('node:worker_threads').parentPort メッセージポートが使用可能です。
  • process.exit() はプログラム全体を停止するのではなく、単一のスレッドのみを停止し、process.abort() は使用できません。
  • process.chdir() およびグループまたはユーザー ID を設定する process メソッドは使用できません。
  • process.env は、特に指定しない限り、親スレッドの環境変数のコピーです。1 つのコピーへの変更は、他のスレッドには表示されず、ネイティブアドオンにも表示されません (worker.SHARE_ENVWorker コンストラクターへの env オプションとして渡されない限り)。Windows では、メインスレッドとは異なり、環境変数のコピーは大文字と小文字を区別して動作します。
  • process.title は変更できません。
  • シグナルは process.on('...') を介して配信されません。
  • worker.terminate() が呼び出された結果として、実行がいつでも停止する可能性があります。
  • 親プロセスからの IPC チャネルはアクセスできません。
  • trace_events モジュールはサポートされていません。
  • ネイティブアドオンは、特定の条件を満たしている場合にのみ、複数のスレッドからロードできます。

他の Worker 内で Worker インスタンスを作成することは可能です。

Web Workers および node:cluster モジュールと同様に、スレッド間のメッセージパッシングを通じて双方向通信を実現できます。内部的には、Worker には、Worker の作成時にすでに関連付けられている MessagePort の組み込みペアがあります。親側の MessagePort オブジェクトは直接公開されていませんが、その機能は親スレッドの Worker オブジェクトに対する worker.postMessage() および worker.on('message') イベントを通じて公開されます。

カスタムメッセージングチャネルを作成するには (関心の分離を促進するため、デフォルトのグローバルチャネルを使用するよりも推奨されます)、いずれかのスレッドで MessageChannel オブジェクトを作成し、グローバルチャネルなど、既存のチャネルを介して、その MessageChannelMessagePort のいずれかを他のスレッドに渡すことができます。

メッセージの渡し方や、スレッドの壁を越えて正常に転送できる 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();
  });
} 

new Worker(filename[, options])#

  • filename <string> | <URL> Worker のメインスクリプトまたはモジュールへのパス。絶対パスまたは ./ または ../ で始まる (つまり、現在の作業ディレクトリに対する相対パス) 相対パス、または file: または data: プロトコルを使用する WHATWG URL オブジェクトである必要があります。data: URL を使用する場合、データは ECMAScript モジュールローダーを使用して MIME タイプに基づいて解釈されます。options.evaltrue の場合、これはパスではなく JavaScript コードを含む文字列です。
  • options <Object>
    • argv <any[]> ワーカーの process.argv に文字列化されて追加される引数のリスト。これはほとんど workerData と似ていますが、値はスクリプトに CLI オプションとして渡されたかのように、グローバルな 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 は書き込み可能なストリームを提供し、その内容はワーカー内で process.stdin として表示されます。デフォルトでは、データは提供されません。
    • stdout <boolean> これを true に設定すると、worker.stdout は自動的に親プロセスの process.stdout にパイプされません。
    • stderr <boolean> これを true に設定すると、worker.stderr は自動的に親プロセスの process.stderr にパイプされません。
    • workerData <any> クローンされ、require('node:worker_threads').workerData として利用可能になる JavaScript の値。クローンは、HTML 構造化クローンアルゴリズムで説明されているように行われ、オブジェクトをクローンできない場合 (例えば、function が含まれている場合) はエラーがスローされます。
    • trackUnmanagedFds <boolean> これを true に設定すると、ワーカーは fs.open() および fs.close() を介して管理される生のファイル記述子を追跡し、ネットワークソケットや FileHandle API を介して管理されるファイル記述子などの他のリソースと同様に、ワーカーが終了するとそれらを閉じます。このオプションは、すべてのネストされた Worker に自動的に継承されます。デフォルト: true
    • transferList <Object[]> 1 つ以上の MessagePort のようなオブジェクトが workerData で渡される場合、それらの項目には 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> スレッドのデフォルトの最大スタックサイズ。小さい値を設定すると、ワーカーインスタンスが使用できなくなる可能性があります。デフォルト: 4
    • name <string> デバッグ/識別用にワーカーのタイトルに追加されるオプションの name。最終的なタイトルは [worker ${id}] ${name} になります。デフォルト: ''

イベント: 'error'#

ワーカー スレッドがキャッチされない例外をスローした場合、'error' イベントが発行されます。その場合、ワーカーは終了します。

イベント: 'exit'#

ワーカーが停止すると、'exit' イベントが発行されます。ワーカーが process.exit() を呼び出して終了した場合、exitCode パラメータは渡された終了コードになります。ワーカーが終了した場合は、exitCode パラメータは 1 になります。

これは、すべての Worker インスタンスから発行される最後のイベントです。

イベント: 'message'#

  • value <any> 送信された値

ワーカー スレッドが require('node:worker_threads').parentPort.postMessage() を呼び出した場合、'message' イベントが発行されます。詳細については、port.on('message') イベントを参照してください。

ワーカー スレッドから送信されたすべてのメッセージは、Worker オブジェクトで 'exit' イベント が発行される前に発行されます。

イベント: 'messageerror'#

  • error <Error> エラー オブジェクト

メッセージのデシリアライズに失敗した場合、'messageerror' イベントが発生します。

イベント: 'online'#

ワーカー スレッドが JavaScript コードの実行を開始すると、'online' イベントが発行されます。

worker.getHeapSnapshot([options])#

  • options <Object>
    • exposeInternals <boolean> true の場合、ヒープスナップショットに内部情報を公開します。デフォルト: false
    • exposeNumericValues <boolean> true の場合、人工的なフィールドに数値データを公開します。デフォルト: false
  • 戻り値: <Promise> V8 ヒープスナップショットを含む Readable Stream の Promise

ワーカーの現在の状態の V8 スナップショットの Readable Stream を返します。詳細については、v8.getHeapSnapshot() を参照してください。

ワーカー スレッドが実行されていない場合 (これは 'exit' イベント が発行される前に発生する可能性があります)、返される PromiseERR_WORKER_NOT_RUNNING エラーですぐに拒否されます。

worker.performance#

ワーカーインスタンスからパフォーマンス情報を照会するために使用できるオブジェクト。perf_hooks.performance と同様です。

performance.eventLoopUtilization([utilization1[, utilization2]])#
  • utilization1 <Object> eventLoopUtilization() の以前の呼び出しの結果。
  • utilization2 <Object> utilization1 より前の eventLoopUtilization() の以前の呼び出しの結果。
  • 戻り値: <Object>

perf_hooks eventLoopUtilization() と同じ呼び出しですが、ワーカーインスタンスの値が返される点が異なります。

1 つの違いは、メインスレッドとは異なり、ワーカー内のブートストラップはイベントループ内で行われることです。そのため、ワーカーのスクリプトの実行が開始されると、イベントループの使用率がすぐに利用可能になります。

増加しない idle 時間は、ワーカーがブートストラップでスタックしていることを示すものではありません。次の例は、ワーカーのライフタイム全体で idle 時間が累積しないにもかかわらず、メッセージを処理できることを示しています。

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

ワーカーのイベントループの使用率は、'online' イベント が発行された後にのみ利用可能になり、これより前または 'exit' イベント の後に呼び出された場合、すべてのプロパティの値は 0 になります。

worker.postMessage(value[, transferList])#

require('node:worker_threads').parentPort.on('message') を介して受信されるメッセージをワーカーに送信します。詳細については、port.postMessage() を参照してください。

worker.ref()#

unref() の反対で、以前に unref() されたワーカーで ref() を呼び出しても、それが唯一のアクティブなハンドルである場合、プログラムは終了しません (デフォルトの動作)。ワーカーが ref() されている場合、再度 ref() を呼び出しても効果はありません。

worker.resourceLimits#

このワーカー スレッドの JS エンジンリソース制約のセットを提供します。resourceLimits オプションが Worker コンストラクタに渡された場合、これはその値と一致します。

ワーカーが停止した場合、戻り値は空のオブジェクトになります。

worker.stderr#

これは、ワーカー スレッド内で process.stderr に書き込まれたデータを含む読み取り可能なストリームです。stderr: trueWorker コンストラクターに渡されなかった場合、データは親スレッドの process.stderr ストリームにパイプされます。

worker.stdin#

stdin: trueWorker コンストラクターに渡された場合、これは書き込み可能なストリームです。このストリームに書き込まれたデータは、ワーカー スレッド内で process.stdin として利用可能になります。

worker.stdout#

これは、ワーカー スレッド内で process.stdout に書き込まれたデータを含む読み取り可能なストリームです。stdout: trueWorker コンストラクターに渡されなかった場合、データは親スレッドの process.stdout ストリームにパイプされます。

worker.terminate()#

可能な限り早くワーカー スレッド内のすべての JavaScript 実行を停止します。'exit' イベント が発行されたときに満たされる終了コードの Promise を返します。

worker.threadId#

参照されているスレッドの整数識別子。ワーカー スレッド内では、require('node:worker_threads').threadId として利用可能です。この値は、単一のプロセス内の各 Worker インスタンスに対して一意です。

worker.unref()#

ワーカーで unref() を呼び出すと、これがイベント システムで唯一のアクティブなハンドルである場合にスレッドを終了させることができます。ワーカーがすでに unref() されている場合、再度 unref() を呼び出しても効果はありません。

注釈#

stdio の同期的なブロッキング#

Worker は、stdio とのインタラクションを実装するために <MessagePort> を介したメッセージ パッシングを利用します。これは、Worker から発信された stdio 出力が、Node.js イベント ループをブロックしている受信側の同期コードによってブロックされる可能性があることを意味します。

import {
  Worker,
  isMainThread,
} from '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');
}

プリロード スクリプトからのワーカー スレッドの起動#

プリロード スクリプト(-r コマンドライン フラグを使用してロードおよび実行されるスクリプト)からワーカー スレッドを起動する際は注意が必要です。execArgv オプションが明示的に設定されていない限り、新しいワーカー スレッドは実行中のプロセスからコマンドライン フラグを自動的に継承し、メイン スレッドと同じプリロード スクリプトをプリロードします。プリロード スクリプトが無条件にワーカー スレッドを起動する場合、スレッドが生成されるたびに別のスレッドが生成され、アプリケーションがクラッシュします。