Node.js v21.7.2 ドキュメント
- Node.js v21.7.2
-
► 目次
- ワーカー スレッド
worker.getEnvironmentData(key)
worker.isMainThread
worker.markAsUntransferable(object)
worker.isMarkedAsUntransferable(object)
worker.moveMessagePortToContext(port, contextifiedSandbox)
worker.parentPort
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()
- 注
- ワーカー スレッド
-
► インデックス
- アサーション テスト
- 非同期コンテキスト追跡
- Async Hooks
- Buffer
- C++ アドオン
- Node-API を使用した C/C++ アドオン
- C++ エンベダー API
- 子プロセス
- Cluster
- コマンドライン オプション
- Console
- Corepack
- Crypto
- デバッガー
- 非推奨 API
- Diagnostics Channel
- DNS
- Domain
- Errors
- Events
- ファイルシステム
- グローバル
- HTTP
- HTTP/2
- HTTPS
- Inspector
- 国際化
- モジュール: CommonJS モジュール
- モジュール: ECMAScript モジュール
- モジュール:
node:module
API - モジュール: パッケージ
- Net
- OS
- Path
- パフォーマンス フック
- パーミッション
- Process
- Punycode
- クエリ文字列
- Readline
- REPL
- Report
- 単一実行可能アプリケーション
- Stream
- 文字列デコーダー
- テストランナー
- タイマー
- TLS/SSL
- トレース イベント
- TTY
- UDP/データグラム
- URL
- ユーティリティ
- V8
- VM
- WASI
- Web Crypto API
- Web Streams API
- ワーカー スレッド
- Zlib
- ► その他のバージョン
- ► オプション
ワーカー スレッド#
ソースコード: lib/worker_threads.js
node:worker_threads
モジュールを使用すると、JavaScript を並行して実行するスレッドを使用できます。アクセスするには、
const worker = require('node:worker_threads');
ワーカー (スレッド) は、CPU 負荷の高い JavaScript 操作を実行するのに役立ちます。I/O 負荷の高い作業にはあまり役立ちません。Node.js に組み込まれている非同期 I/O 操作の方が、ワーカーよりも効率的です。
child_process
や cluster
とは異なり、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)
#
ワーカー スレッド内では、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 値。
オブジェクトを転送不可としてマークします。object
が port.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)
#
-
port
<MessagePort> 転送するメッセージ ポート。 -
contextifiedSandbox
<Object>vm.createContext()
メソッドによって返される コンテキスト化されたオブジェクト。 -
戻り値: <MessagePort>
MessagePort
を別の vm
コンテキストに転送します。元の port
オブジェクトは使用できなくなり、返された MessagePort
インスタンスがその場所に置き換わります。
返された MessagePort
は、ターゲット コンテキストのオブジェクトであり、そのグローバル Object
クラスから継承されます。port.onmessage()
リスナーに渡されるオブジェクトもターゲット コンテキストで作成され、そのグローバル Object
クラスから継承されます。
ただし、作成された MessagePort
は EventTarget
から継承されなくなり、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)
#
-
port
<MessagePort> | <BroadcastChannel> -
戻り値: <Object> | <undefined>
指定された 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
インスタンスに自動的に渡されます。value
がundefined
として渡された場合、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
#
- 拡張: <EventTarget>
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])
#
value
<any>transferList
<Object[]>
このチャネルの受信側に JavaScript 値を送信します。value
は、HTML 構造化クローン アルゴリズムと互換性のある方法で転送されます。
特に、JSON
との重要な違いは次のとおりです。
value
には循環参照を含めることができます。value
には、RegExp
、BigInt
、Map
、Set
などの組み込み JS 型のインスタンスを含めることができます。value
には、ArrayBuffer
とSharedArrayBuffer
の両方を使用した型付き配列を含めることができます。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
には、ArrayBuffer
、MessagePort
、および FileHandle
オブジェクトのリストを指定できます。転送後、これらはチャネルの送信側では使用できなくなります (value
に含まれていない場合でも)。子プロセスの場合とは異なり、ネットワークソケットなどのハンドルの転送は現在サポートされていません。
value
に SharedArrayBuffer
インスタンスが含まれている場合、それらはどちらのスレッドからもアクセスできます。これらを 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
を転送または複製できるかどうかは、インスタンスがどのように作成されたかに完全に依存し、確実に判断できないことがよくあります。
ArrayBuffer
に markAsUntransferable()
を使用してマークを付けることで、常に複製され、転送されないように指示できます。
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()
#
- 戻り値: <boolean>
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
#
- 拡張: <EventEmitter>
Worker
クラスは、独立した JavaScript 実行スレッドを表します。ほとんどの Node.js API はその内部で使用できます。
Worker 環境内での重要な違いは次のとおりです。
process.stdin
、process.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_ENV
がWorker
コンストラクターへの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
オブジェクトを作成し、グローバルチャネルなど、既存のチャネルを介して、その 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();
});
}
new Worker(filename[, options])
#
filename
<string> | <URL> Worker のメインスクリプトまたはモジュールへのパス。絶対パスまたは./
または../
で始まる (つまり、現在の作業ディレクトリに対する相対パス) 相対パス、またはfile:
またはdata:
プロトコルを使用する WHATWGURL
オブジェクトである必要があります。data:
URL を使用する場合、データは ECMAScript モジュールローダーを使用して MIME タイプに基づいて解釈されます。options.eval
がtrue
の場合、これはパスではなく 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'
#
err
<Error>
ワーカー スレッドがキャッチされない例外をスローした場合、'error'
イベントが発行されます。その場合、ワーカーは終了します。
イベント: 'exit'
#
exitCode
<integer>
ワーカーが停止すると、'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])
#
ワーカーの現在の状態の V8 スナップショットの Readable Stream を返します。詳細については、v8.getHeapSnapshot()
を参照してください。
ワーカー スレッドが実行されていない場合 (これは 'exit'
イベント が発行される前に発生する可能性があります)、返される Promise
は ERR_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])
#
value
<any>transferList
<Object[]>
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: true
が Worker
コンストラクターに渡されなかった場合、データは親スレッドの process.stderr
ストリームにパイプされます。
worker.stdin
#
stdin: true
が Worker
コンストラクターに渡された場合、これは書き込み可能なストリームです。このストリームに書き込まれたデータは、ワーカー スレッド内で process.stdin
として利用可能になります。
worker.stdout
#
これは、ワーカー スレッド内で process.stdout
に書き込まれたデータを含む読み取り可能なストリームです。stdout: true
が Worker
コンストラクターに渡されなかった場合、データは親スレッドの process.stdout
ストリームにパイプされます。
worker.terminate()
#
- 戻り値: <Promise>
可能な限り早くワーカー スレッド内のすべての 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
オプションが明示的に設定されていない限り、新しいワーカー スレッドは実行中のプロセスからコマンドライン フラグを自動的に継承し、メイン スレッドと同じプリロード スクリプトをプリロードします。プリロード スクリプトが無条件にワーカー スレッドを起動する場合、スレッドが生成されるたびに別のスレッドが生成され、アプリケーションがクラッシュします。