• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Worker threads
2
3<!--introduced_in=v10.5.0-->
4
5> Stability: 2 - Stable
6
7<!-- source_link=lib/worker_threads.js -->
8
9The `node:worker_threads` module enables the use of threads that execute
10JavaScript in parallel. To access it:
11
12```js
13const worker = require('node:worker_threads');
14```
15
16Workers (threads) are useful for performing CPU-intensive JavaScript operations.
17They do not help much with I/O-intensive work. The Node.js built-in
18asynchronous I/O operations are more efficient than Workers can be.
19
20Unlike `child_process` or `cluster`, `worker_threads` can share memory. They do
21so by transferring `ArrayBuffer` instances or sharing `SharedArrayBuffer`
22instances.
23
24```js
25const {
26  Worker, isMainThread, parentPort, workerData,
27} = require('node:worker_threads');
28
29if (isMainThread) {
30  module.exports = function parseJSAsync(script) {
31    return new Promise((resolve, reject) => {
32      const worker = new Worker(__filename, {
33        workerData: script,
34      });
35      worker.on('message', resolve);
36      worker.on('error', reject);
37      worker.on('exit', (code) => {
38        if (code !== 0)
39          reject(new Error(`Worker stopped with exit code ${code}`));
40      });
41    });
42  };
43} else {
44  const { parse } = require('some-js-parsing-library');
45  const script = workerData;
46  parentPort.postMessage(parse(script));
47}
48```
49
50The above example spawns a Worker thread for each `parseJSAsync()` call. In
51practice, use a pool of Workers for these kinds of tasks. Otherwise, the
52overhead of creating Workers would likely exceed their benefit.
53
54When implementing a worker pool, use the [`AsyncResource`][] API to inform
55diagnostic tools (e.g. to provide asynchronous stack traces) about the
56correlation between tasks and their outcomes. See
57["Using `AsyncResource` for a `Worker` thread pool"][async-resource-worker-pool]
58in the `async_hooks` documentation for an example implementation.
59
60Worker threads inherit non-process-specific options by default. Refer to
61[`Worker constructor options`][] to know how to customize worker thread options,
62specifically `argv` and `execArgv` options.
63
64## `worker.getEnvironmentData(key)`
65
66<!-- YAML
67added:
68  - v15.12.0
69  - v14.18.0
70changes:
71  - version: v17.5.0
72    pr-url: https://github.com/nodejs/node/pull/41272
73    description: No longer experimental.
74-->
75
76* `key` {any} Any arbitrary, cloneable JavaScript value that can be used as a
77  {Map} key.
78* Returns: {any}
79
80Within a worker thread, `worker.getEnvironmentData()` returns a clone
81of data passed to the spawning thread's `worker.setEnvironmentData()`.
82Every new `Worker` receives its own copy of the environment data
83automatically.
84
85```js
86const {
87  Worker,
88  isMainThread,
89  setEnvironmentData,
90  getEnvironmentData,
91} = require('node:worker_threads');
92
93if (isMainThread) {
94  setEnvironmentData('Hello', 'World!');
95  const worker = new Worker(__filename);
96} else {
97  console.log(getEnvironmentData('Hello'));  // Prints 'World!'.
98}
99```
100
101## `worker.isMainThread`
102
103<!-- YAML
104added: v10.5.0
105-->
106
107* {boolean}
108
109Is `true` if this code is not running inside of a [`Worker`][] thread.
110
111```js
112const { Worker, isMainThread } = require('node:worker_threads');
113
114if (isMainThread) {
115  // This re-loads the current file inside a Worker instance.
116  new Worker(__filename);
117} else {
118  console.log('Inside Worker!');
119  console.log(isMainThread);  // Prints 'false'.
120}
121```
122
123## `worker.markAsUntransferable(object)`
124
125<!-- YAML
126added:
127  - v14.5.0
128  - v12.19.0
129-->
130
131Mark an object as not transferable. If `object` occurs in the transfer list of
132a [`port.postMessage()`][] call, it is ignored.
133
134In particular, this makes sense for objects that can be cloned, rather than
135transferred, and which are used by other objects on the sending side.
136For example, Node.js marks the `ArrayBuffer`s it uses for its
137[`Buffer` pool][`Buffer.allocUnsafe()`] with this.
138
139This operation cannot be undone.
140
141```js
142const { MessageChannel, markAsUntransferable } = require('node:worker_threads');
143
144const pooledBuffer = new ArrayBuffer(8);
145const typedArray1 = new Uint8Array(pooledBuffer);
146const typedArray2 = new Float64Array(pooledBuffer);
147
148markAsUntransferable(pooledBuffer);
149
150const { port1 } = new MessageChannel();
151port1.postMessage(typedArray1, [ typedArray1.buffer ]);
152
153// The following line prints the contents of typedArray1 -- it still owns
154// its memory and has been cloned, not transferred. Without
155// `markAsUntransferable()`, this would print an empty Uint8Array.
156// typedArray2 is intact as well.
157console.log(typedArray1);
158console.log(typedArray2);
159```
160
161There is no equivalent to this API in browsers.
162
163## `worker.moveMessagePortToContext(port, contextifiedSandbox)`
164
165<!-- YAML
166added: v11.13.0
167-->
168
169* `port` {MessagePort} The message port to transfer.
170
171* `contextifiedSandbox` {Object} A [contextified][] object as returned by the
172  `vm.createContext()` method.
173
174* Returns: {MessagePort}
175
176Transfer a `MessagePort` to a different [`vm`][] Context. The original `port`
177object is rendered unusable, and the returned `MessagePort` instance
178takes its place.
179
180The returned `MessagePort` is an object in the target context and
181inherits from its global `Object` class. Objects passed to the
182[`port.onmessage()`][] listener are also created in the target context
183and inherit from its global `Object` class.
184
185However, the created `MessagePort` no longer inherits from
186[`EventTarget`][], and only [`port.onmessage()`][] can be used to receive
187events using it.
188
189## `worker.parentPort`
190
191<!-- YAML
192added: v10.5.0
193-->
194
195* {null|MessagePort}
196
197If this thread is a [`Worker`][], this is a [`MessagePort`][]
198allowing communication with the parent thread. Messages sent using
199`parentPort.postMessage()` are available in the parent thread
200using `worker.on('message')`, and messages sent from the parent thread
201using `worker.postMessage()` are available in this thread using
202`parentPort.on('message')`.
203
204```js
205const { Worker, isMainThread, parentPort } = require('node:worker_threads');
206
207if (isMainThread) {
208  const worker = new Worker(__filename);
209  worker.once('message', (message) => {
210    console.log(message);  // Prints 'Hello, world!'.
211  });
212  worker.postMessage('Hello, world!');
213} else {
214  // When a message from the parent thread is received, send it back:
215  parentPort.once('message', (message) => {
216    parentPort.postMessage(message);
217  });
218}
219```
220
221## `worker.receiveMessageOnPort(port)`
222
223<!-- YAML
224added: v12.3.0
225changes:
226  - version: v15.12.0
227    pr-url: https://github.com/nodejs/node/pull/37535
228    description: The port argument can also refer to a `BroadcastChannel` now.
229-->
230
231* `port` {MessagePort|BroadcastChannel}
232
233* Returns: {Object|undefined}
234
235Receive a single message from a given `MessagePort`. If no message is available,
236`undefined` is returned, otherwise an object with a single `message` property
237that contains the message payload, corresponding to the oldest message in the
238`MessagePort`'s queue.
239
240```js
241const { MessageChannel, receiveMessageOnPort } = require('node:worker_threads');
242const { port1, port2 } = new MessageChannel();
243port1.postMessage({ hello: 'world' });
244
245console.log(receiveMessageOnPort(port2));
246// Prints: { message: { hello: 'world' } }
247console.log(receiveMessageOnPort(port2));
248// Prints: undefined
249```
250
251When this function is used, no `'message'` event is emitted and the
252`onmessage` listener is not invoked.
253
254## `worker.resourceLimits`
255
256<!-- YAML
257added:
258 - v13.2.0
259 - v12.16.0
260-->
261
262* {Object}
263  * `maxYoungGenerationSizeMb` {number}
264  * `maxOldGenerationSizeMb` {number}
265  * `codeRangeSizeMb` {number}
266  * `stackSizeMb` {number}
267
268Provides the set of JS engine resource constraints inside this Worker thread.
269If the `resourceLimits` option was passed to the [`Worker`][] constructor,
270this matches its values.
271
272If this is used in the main thread, its value is an empty object.
273
274## `worker.SHARE_ENV`
275
276<!-- YAML
277added: v11.14.0
278-->
279
280* {symbol}
281
282A special value that can be passed as the `env` option of the [`Worker`][]
283constructor, to indicate that the current thread and the Worker thread should
284share read and write access to the same set of environment variables.
285
286```js
287const { Worker, SHARE_ENV } = require('node:worker_threads');
288new Worker('process.env.SET_IN_WORKER = "foo"', { eval: true, env: SHARE_ENV })
289  .on('exit', () => {
290    console.log(process.env.SET_IN_WORKER);  // Prints 'foo'.
291  });
292```
293
294## `worker.setEnvironmentData(key[, value])`
295
296<!-- YAML
297added:
298  - v15.12.0
299  - v14.18.0
300changes:
301  - version: v17.5.0
302    pr-url: https://github.com/nodejs/node/pull/41272
303    description: No longer experimental.
304-->
305
306* `key` {any} Any arbitrary, cloneable JavaScript value that can be used as a
307  {Map} key.
308* `value` {any} Any arbitrary, cloneable JavaScript value that will be cloned
309  and passed automatically to all new `Worker` instances. If `value` is passed
310  as `undefined`, any previously set value for the `key` will be deleted.
311
312The `worker.setEnvironmentData()` API sets the content of
313`worker.getEnvironmentData()` in the current thread and all new `Worker`
314instances spawned from the current context.
315
316## `worker.threadId`
317
318<!-- YAML
319added: v10.5.0
320-->
321
322* {integer}
323
324An integer identifier for the current thread. On the corresponding worker object
325(if there is any), it is available as [`worker.threadId`][].
326This value is unique for each [`Worker`][] instance inside a single process.
327
328## `worker.workerData`
329
330<!-- YAML
331added: v10.5.0
332-->
333
334An arbitrary JavaScript value that contains a clone of the data passed
335to this thread's `Worker` constructor.
336
337The data is cloned as if using [`postMessage()`][`port.postMessage()`],
338according to the [HTML structured clone algorithm][].
339
340```js
341const { Worker, isMainThread, workerData } = require('node:worker_threads');
342
343if (isMainThread) {
344  const worker = new Worker(__filename, { workerData: 'Hello, world!' });
345} else {
346  console.log(workerData);  // Prints 'Hello, world!'.
347}
348```
349
350## Class: `BroadcastChannel extends EventTarget`
351
352<!-- YAML
353added: v15.4.0
354changes:
355  - version: v18.0.0
356    pr-url: https://github.com/nodejs/node/pull/41271
357    description: No longer experimental.
358-->
359
360Instances of `BroadcastChannel` allow asynchronous one-to-many communication
361with all other `BroadcastChannel` instances bound to the same channel name.
362
363```js
364'use strict';
365
366const {
367  isMainThread,
368  BroadcastChannel,
369  Worker,
370} = require('node:worker_threads');
371
372const bc = new BroadcastChannel('hello');
373
374if (isMainThread) {
375  let c = 0;
376  bc.onmessage = (event) => {
377    console.log(event.data);
378    if (++c === 10) bc.close();
379  };
380  for (let n = 0; n < 10; n++)
381    new Worker(__filename);
382} else {
383  bc.postMessage('hello from every worker');
384  bc.close();
385}
386```
387
388### `new BroadcastChannel(name)`
389
390<!-- YAML
391added: v15.4.0
392-->
393
394* `name` {any} The name of the channel to connect to. Any JavaScript value
395  that can be converted to a string using `` `${name}` `` is permitted.
396
397### `broadcastChannel.close()`
398
399<!-- YAML
400added: v15.4.0
401-->
402
403Closes the `BroadcastChannel` connection.
404
405### `broadcastChannel.onmessage`
406
407<!-- YAML
408added: v15.4.0
409-->
410
411* Type: {Function} Invoked with a single `MessageEvent` argument
412  when a message is received.
413
414### `broadcastChannel.onmessageerror`
415
416<!-- YAML
417added: v15.4.0
418-->
419
420* Type: {Function} Invoked with a received message cannot be
421  deserialized.
422
423### `broadcastChannel.postMessage(message)`
424
425<!-- YAML
426added: v15.4.0
427-->
428
429* `message` {any} Any cloneable JavaScript value.
430
431### `broadcastChannel.ref()`
432
433<!-- YAML
434added: v15.4.0
435-->
436
437Opposite of `unref()`. Calling `ref()` on a previously `unref()`ed
438BroadcastChannel does _not_ let the program exit if it's the only active handle
439left (the default behavior). If the port is `ref()`ed, calling `ref()` again
440has no effect.
441
442### `broadcastChannel.unref()`
443
444<!-- YAML
445added: v15.4.0
446-->
447
448Calling `unref()` on a BroadcastChannel allows the thread to exit if this
449is the only active handle in the event system. If the BroadcastChannel is
450already `unref()`ed calling `unref()` again has no effect.
451
452## Class: `MessageChannel`
453
454<!-- YAML
455added: v10.5.0
456-->
457
458Instances of the `worker.MessageChannel` class represent an asynchronous,
459two-way communications channel.
460The `MessageChannel` has no methods of its own. `new MessageChannel()`
461yields an object with `port1` and `port2` properties, which refer to linked
462[`MessagePort`][] instances.
463
464```js
465const { MessageChannel } = require('node:worker_threads');
466
467const { port1, port2 } = new MessageChannel();
468port1.on('message', (message) => console.log('received', message));
469port2.postMessage({ foo: 'bar' });
470// Prints: received { foo: 'bar' } from the `port1.on('message')` listener
471```
472
473## Class: `MessagePort`
474
475<!-- YAML
476added: v10.5.0
477changes:
478  - version:
479    - v14.7.0
480    pr-url: https://github.com/nodejs/node/pull/34057
481    description: This class now inherits from `EventTarget` rather than
482                 from `EventEmitter`.
483-->
484
485* Extends: {EventTarget}
486
487Instances of the `worker.MessagePort` class represent one end of an
488asynchronous, two-way communications channel. It can be used to transfer
489structured data, memory regions and other `MessagePort`s between different
490[`Worker`][]s.
491
492This implementation matches [browser `MessagePort`][]s.
493
494### Event: `'close'`
495
496<!-- YAML
497added: v10.5.0
498-->
499
500The `'close'` event is emitted once either side of the channel has been
501disconnected.
502
503```js
504const { MessageChannel } = require('node:worker_threads');
505const { port1, port2 } = new MessageChannel();
506
507// Prints:
508//   foobar
509//   closed!
510port2.on('message', (message) => console.log(message));
511port2.on('close', () => console.log('closed!'));
512
513port1.postMessage('foobar');
514port1.close();
515```
516
517### Event: `'message'`
518
519<!-- YAML
520added: v10.5.0
521-->
522
523* `value` {any} The transmitted value
524
525The `'message'` event is emitted for any incoming message, containing the cloned
526input of [`port.postMessage()`][].
527
528Listeners on this event receive a clone of the `value` parameter as passed
529to `postMessage()` and no further arguments.
530
531### Event: `'messageerror'`
532
533<!-- YAML
534added:
535  - v14.5.0
536  - v12.19.0
537-->
538
539* `error` {Error} An Error object
540
541The `'messageerror'` event is emitted when deserializing a message failed.
542
543Currently, this event is emitted when there is an error occurring while
544instantiating the posted JS object on the receiving end. Such situations
545are rare, but can happen, for instance, when certain Node.js API objects
546are received in a `vm.Context` (where Node.js APIs are currently
547unavailable).
548
549### `port.close()`
550
551<!-- YAML
552added: v10.5.0
553-->
554
555Disables further sending of messages on either side of the connection.
556This method can be called when no further communication will happen over this
557`MessagePort`.
558
559The [`'close'` event][] is emitted on both `MessagePort` instances that
560are part of the channel.
561
562### `port.postMessage(value[, transferList])`
563
564<!-- YAML
565added: v10.5.0
566changes:
567  - version:
568      - v15.14.0
569      - v14.18.0
570    pr-url: https://github.com/nodejs/node/pull/37917
571    description: Add 'BlockList' to the list of cloneable types.
572  - version:
573      - v15.9.0
574      - v14.18.0
575    pr-url: https://github.com/nodejs/node/pull/37155
576    description: Add 'Histogram' types to the list of cloneable types.
577  - version: v15.6.0
578    pr-url: https://github.com/nodejs/node/pull/36804
579    description: Added `X509Certificate` to the list of cloneable types.
580  - version: v15.0.0
581    pr-url: https://github.com/nodejs/node/pull/35093
582    description: Added `CryptoKey` to the list of cloneable types.
583  - version:
584    - v14.5.0
585    - v12.19.0
586    pr-url: https://github.com/nodejs/node/pull/33360
587    description: Added `KeyObject` to the list of cloneable types.
588  - version:
589    - v14.5.0
590    - v12.19.0
591    pr-url: https://github.com/nodejs/node/pull/33772
592    description: Added `FileHandle` to the list of transferable types.
593-->
594
595* `value` {any}
596* `transferList` {Object\[]}
597
598Sends a JavaScript value to the receiving side of this channel.
599`value` is transferred in a way which is compatible with
600the [HTML structured clone algorithm][].
601
602In particular, the significant differences to `JSON` are:
603
604* `value` may contain circular references.
605* `value` may contain instances of builtin JS types such as `RegExp`s,
606  `BigInt`s, `Map`s, `Set`s, etc.
607* `value` may contain typed arrays, both using `ArrayBuffer`s
608  and `SharedArrayBuffer`s.
609* `value` may contain [`WebAssembly.Module`][] instances.
610* `value` may not contain native (C++-backed) objects other than:
611  * {CryptoKey}s,
612  * {FileHandle}s,
613  * {Histogram}s,
614  * {KeyObject}s,
615  * {MessagePort}s,
616  * {net.BlockList}s,
617  * {net.SocketAddress}es,
618  * {X509Certificate}s.
619
620```js
621const { MessageChannel } = require('node:worker_threads');
622const { port1, port2 } = new MessageChannel();
623
624port1.on('message', (message) => console.log(message));
625
626const circularData = {};
627circularData.foo = circularData;
628// Prints: { foo: [Circular] }
629port2.postMessage(circularData);
630```
631
632`transferList` may be a list of [`ArrayBuffer`][], [`MessagePort`][], and
633[`FileHandle`][] objects.
634After transferring, they are not usable on the sending side of the channel
635anymore (even if they are not contained in `value`). Unlike with
636[child processes][], transferring handles such as network sockets is currently
637not supported.
638
639If `value` contains [`SharedArrayBuffer`][] instances, those are accessible
640from either thread. They cannot be listed in `transferList`.
641
642`value` may still contain `ArrayBuffer` instances that are not in
643`transferList`; in that case, the underlying memory is copied rather than moved.
644
645```js
646const { MessageChannel } = require('node:worker_threads');
647const { port1, port2 } = new MessageChannel();
648
649port1.on('message', (message) => console.log(message));
650
651const uint8Array = new Uint8Array([ 1, 2, 3, 4 ]);
652// This posts a copy of `uint8Array`:
653port2.postMessage(uint8Array);
654// This does not copy data, but renders `uint8Array` unusable:
655port2.postMessage(uint8Array, [ uint8Array.buffer ]);
656
657// The memory for the `sharedUint8Array` is accessible from both the
658// original and the copy received by `.on('message')`:
659const sharedUint8Array = new Uint8Array(new SharedArrayBuffer(4));
660port2.postMessage(sharedUint8Array);
661
662// This transfers a freshly created message port to the receiver.
663// This can be used, for example, to create communication channels between
664// multiple `Worker` threads that are children of the same parent thread.
665const otherChannel = new MessageChannel();
666port2.postMessage({ port: otherChannel.port1 }, [ otherChannel.port1 ]);
667```
668
669The message object is cloned immediately, and can be modified after
670posting without having side effects.
671
672For more information on the serialization and deserialization mechanisms
673behind this API, see the [serialization API of the `node:v8` module][v8.serdes].
674
675#### Considerations when transferring TypedArrays and Buffers
676
677All `TypedArray` and `Buffer` instances are views over an underlying
678`ArrayBuffer`. That is, it is the `ArrayBuffer` that actually stores
679the raw data while the `TypedArray` and `Buffer` objects provide a
680way of viewing and manipulating the data. It is possible and common
681for multiple views to be created over the same `ArrayBuffer` instance.
682Great care must be taken when using a transfer list to transfer an
683`ArrayBuffer` as doing so causes all `TypedArray` and `Buffer`
684instances that share that same `ArrayBuffer` to become unusable.
685
686```js
687const ab = new ArrayBuffer(10);
688
689const u1 = new Uint8Array(ab);
690const u2 = new Uint16Array(ab);
691
692console.log(u2.length);  // prints 5
693
694port.postMessage(u1, [u1.buffer]);
695
696console.log(u2.length);  // prints 0
697```
698
699For `Buffer` instances, specifically, whether the underlying
700`ArrayBuffer` can be transferred or cloned depends entirely on how
701instances were created, which often cannot be reliably determined.
702
703An `ArrayBuffer` can be marked with [`markAsUntransferable()`][] to indicate
704that it should always be cloned and never transferred.
705
706Depending on how a `Buffer` instance was created, it may or may
707not own its underlying `ArrayBuffer`. An `ArrayBuffer` must not
708be transferred unless it is known that the `Buffer` instance
709owns it. In particular, for `Buffer`s created from the internal
710`Buffer` pool (using, for instance `Buffer.from()` or `Buffer.allocUnsafe()`),
711transferring them is not possible and they are always cloned,
712which sends a copy of the entire `Buffer` pool.
713This behavior may come with unintended higher memory
714usage and possible security concerns.
715
716See [`Buffer.allocUnsafe()`][] for more details on `Buffer` pooling.
717
718The `ArrayBuffer`s for `Buffer` instances created using
719`Buffer.alloc()` or `Buffer.allocUnsafeSlow()` can always be
720transferred but doing so renders all other existing views of
721those `ArrayBuffer`s unusable.
722
723#### Considerations when cloning objects with prototypes, classes, and accessors
724
725Because object cloning uses the [HTML structured clone algorithm][],
726non-enumerable properties, property accessors, and object prototypes are
727not preserved. In particular, [`Buffer`][] objects will be read as
728plain [`Uint8Array`][]s on the receiving side, and instances of JavaScript
729classes will be cloned as plain JavaScript objects.
730
731```js
732const b = Symbol('b');
733
734class Foo {
735  #a = 1;
736  constructor() {
737    this[b] = 2;
738    this.c = 3;
739  }
740
741  get d() { return 4; }
742}
743
744const { port1, port2 } = new MessageChannel();
745
746port1.onmessage = ({ data }) => console.log(data);
747
748port2.postMessage(new Foo());
749
750// Prints: { c: 3 }
751```
752
753This limitation extends to many built-in objects, such as the global `URL`
754object:
755
756```js
757const { port1, port2 } = new MessageChannel();
758
759port1.onmessage = ({ data }) => console.log(data);
760
761port2.postMessage(new URL('https://example.org'));
762
763// Prints: { }
764```
765
766### `port.hasRef()`
767
768<!-- YAML
769added: v18.1.0
770-->
771
772> Stability: 1 - Experimental
773
774* Returns: {boolean}
775
776If true, the `MessagePort` object will keep the Node.js event loop active.
777
778### `port.ref()`
779
780<!-- YAML
781added: v10.5.0
782-->
783
784Opposite of `unref()`. Calling `ref()` on a previously `unref()`ed port does
785_not_ let the program exit if it's the only active handle left (the default
786behavior). If the port is `ref()`ed, calling `ref()` again has no effect.
787
788If listeners are attached or removed using `.on('message')`, the port
789is `ref()`ed and `unref()`ed automatically depending on whether
790listeners for the event exist.
791
792### `port.start()`
793
794<!-- YAML
795added: v10.5.0
796-->
797
798Starts receiving messages on this `MessagePort`. When using this port
799as an event emitter, this is called automatically once `'message'`
800listeners are attached.
801
802This method exists for parity with the Web `MessagePort` API. In Node.js,
803it is only useful for ignoring messages when no event listener is present.
804Node.js also diverges in its handling of `.onmessage`. Setting it
805automatically calls `.start()`, but unsetting it lets messages queue up
806until a new handler is set or the port is discarded.
807
808### `port.unref()`
809
810<!-- YAML
811added: v10.5.0
812-->
813
814Calling `unref()` on a port allows the thread to exit if this is the only
815active handle in the event system. If the port is already `unref()`ed calling
816`unref()` again has no effect.
817
818If listeners are attached or removed using `.on('message')`, the port is
819`ref()`ed and `unref()`ed automatically depending on whether
820listeners for the event exist.
821
822## Class: `Worker`
823
824<!-- YAML
825added: v10.5.0
826-->
827
828* Extends: {EventEmitter}
829
830The `Worker` class represents an independent JavaScript execution thread.
831Most Node.js APIs are available inside of it.
832
833Notable differences inside a Worker environment are:
834
835* The [`process.stdin`][], [`process.stdout`][], and [`process.stderr`][]
836  streams may be redirected by the parent thread.
837* The [`require('node:worker_threads').isMainThread`][] property is set to `false`.
838* The [`require('node:worker_threads').parentPort`][] message port is available.
839* [`process.exit()`][] does not stop the whole program, just the single thread,
840  and [`process.abort()`][] is not available.
841* [`process.chdir()`][] and `process` methods that set group or user ids
842  are not available.
843* [`process.env`][] is a copy of the parent thread's environment variables,
844  unless otherwise specified. Changes to one copy are not visible in other
845  threads, and are not visible to native add-ons (unless
846  [`worker.SHARE_ENV`][] is passed as the `env` option to the
847  [`Worker`][] constructor).
848* [`process.title`][] cannot be modified.
849* Signals are not delivered through [`process.on('...')`][Signals events].
850* Execution may stop at any point as a result of [`worker.terminate()`][]
851  being invoked.
852* IPC channels from parent processes are not accessible.
853* The [`trace_events`][] module is not supported.
854* Native add-ons can only be loaded from multiple threads if they fulfill
855  [certain conditions][Addons worker support].
856
857Creating `Worker` instances inside of other `Worker`s is possible.
858
859Like [Web Workers][] and the [`node:cluster` module][], two-way communication
860can be achieved through inter-thread message passing. Internally, a `Worker` has
861a built-in pair of [`MessagePort`][]s that are already associated with each
862other when the `Worker` is created. While the `MessagePort` object on the parent
863side is not directly exposed, its functionalities are exposed through
864[`worker.postMessage()`][] and the [`worker.on('message')`][] event
865on the `Worker` object for the parent thread.
866
867To create custom messaging channels (which is encouraged over using the default
868global channel because it facilitates separation of concerns), users can create
869a `MessageChannel` object on either thread and pass one of the
870`MessagePort`s on that `MessageChannel` to the other thread through a
871pre-existing channel, such as the global one.
872
873See [`port.postMessage()`][] for more information on how messages are passed,
874and what kind of JavaScript values can be successfully transported through
875the thread barrier.
876
877```js
878const assert = require('node:assert');
879const {
880  Worker, MessageChannel, MessagePort, isMainThread, parentPort,
881} = require('node:worker_threads');
882if (isMainThread) {
883  const worker = new Worker(__filename);
884  const subChannel = new MessageChannel();
885  worker.postMessage({ hereIsYourPort: subChannel.port1 }, [subChannel.port1]);
886  subChannel.port2.on('message', (value) => {
887    console.log('received:', value);
888  });
889} else {
890  parentPort.once('message', (value) => {
891    assert(value.hereIsYourPort instanceof MessagePort);
892    value.hereIsYourPort.postMessage('the worker is sending this');
893    value.hereIsYourPort.close();
894  });
895}
896```
897
898### `new Worker(filename[, options])`
899
900<!-- YAML
901added: v10.5.0
902changes:
903  - version: v18.16.0
904    pr-url: https://github.com/nodejs/node/pull/46832
905    description: Added support for a `name` option, which allows
906                 adding a name to worker title for debugging.
907  - version: v14.9.0
908    pr-url: https://github.com/nodejs/node/pull/34584
909    description: The `filename` parameter can be a WHATWG `URL` object using
910                 `data:` protocol.
911  - version: v14.9.0
912    pr-url: https://github.com/nodejs/node/pull/34394
913    description: The `trackUnmanagedFds` option was set to `true` by default.
914  - version:
915    - v14.6.0
916    - v12.19.0
917    pr-url: https://github.com/nodejs/node/pull/34303
918    description: The `trackUnmanagedFds` option was introduced.
919  - version:
920     - v13.13.0
921     - v12.17.0
922    pr-url: https://github.com/nodejs/node/pull/32278
923    description: The `transferList` option was introduced.
924  - version:
925     - v13.12.0
926     - v12.17.0
927    pr-url: https://github.com/nodejs/node/pull/31664
928    description: The `filename` parameter can be a WHATWG `URL` object using
929                 `file:` protocol.
930  - version:
931     - v13.4.0
932     - v12.16.0
933    pr-url: https://github.com/nodejs/node/pull/30559
934    description: The `argv` option was introduced.
935  - version:
936     - v13.2.0
937     - v12.16.0
938    pr-url: https://github.com/nodejs/node/pull/26628
939    description: The `resourceLimits` option was introduced.
940-->
941
942* `filename` {string|URL} The path to the Worker's main script or module. Must
943  be either an absolute path or a relative path (i.e. relative to the
944  current working directory) starting with `./` or `../`, or a WHATWG `URL`
945  object using `file:` or `data:` protocol.
946  When using a [`data:` URL][], the data is interpreted based on MIME type using
947  the [ECMAScript module loader][].
948  If `options.eval` is `true`, this is a string containing JavaScript code
949  rather than a path.
950* `options` {Object}
951  * `argv` {any\[]} List of arguments which would be stringified and appended to
952    `process.argv` in the worker. This is mostly similar to the `workerData`
953    but the values are available on the global `process.argv` as if they
954    were passed as CLI options to the script.
955  * `env` {Object} If set, specifies the initial value of `process.env` inside
956    the Worker thread. As a special value, [`worker.SHARE_ENV`][] may be used
957    to specify that the parent thread and the child thread should share their
958    environment variables; in that case, changes to one thread's `process.env`
959    object affect the other thread as well. **Default:** `process.env`.
960  * `eval` {boolean} If `true` and the first argument is a `string`, interpret
961    the first argument to the constructor as a script that is executed once the
962    worker is online.
963  * `execArgv` {string\[]} List of node CLI options passed to the worker.
964    V8 options (such as `--max-old-space-size`) and options that affect the
965    process (such as `--title`) are not supported. If set, this is provided
966    as [`process.execArgv`][] inside the worker. By default, options are
967    inherited from the parent thread.
968  * `stdin` {boolean} If this is set to `true`, then `worker.stdin`
969    provides a writable stream whose contents appear as `process.stdin`
970    inside the Worker. By default, no data is provided.
971  * `stdout` {boolean} If this is set to `true`, then `worker.stdout` is
972    not automatically piped through to `process.stdout` in the parent.
973  * `stderr` {boolean} If this is set to `true`, then `worker.stderr` is
974    not automatically piped through to `process.stderr` in the parent.
975  * `workerData` {any} Any JavaScript value that is cloned and made
976    available as [`require('node:worker_threads').workerData`][]. The cloning
977    occurs as described in the [HTML structured clone algorithm][], and an error
978    is thrown if the object cannot be cloned (e.g. because it contains
979    `function`s).
980  * `trackUnmanagedFds` {boolean} If this is set to `true`, then the Worker
981    tracks raw file descriptors managed through [`fs.open()`][] and
982    [`fs.close()`][], and closes them when the Worker exits, similar to other
983    resources like network sockets or file descriptors managed through
984    the [`FileHandle`][] API. This option is automatically inherited by all
985    nested `Worker`s. **Default:** `true`.
986  * `transferList` {Object\[]} If one or more `MessagePort`-like objects
987    are passed in `workerData`, a `transferList` is required for those
988    items or [`ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST`][] is thrown.
989    See [`port.postMessage()`][] for more information.
990  * `resourceLimits` {Object} An optional set of resource limits for the new JS
991    engine instance. Reaching these limits leads to termination of the `Worker`
992    instance. These limits only affect the JS engine, and no external data,
993    including no `ArrayBuffer`s. Even if these limits are set, the process may
994    still abort if it encounters a global out-of-memory situation.
995    * `maxOldGenerationSizeMb` {number} The maximum size of the main heap in
996      MB. If the command-line argument [`--max-old-space-size`][] is set, it
997      overrides this setting.
998    * `maxYoungGenerationSizeMb` {number} The maximum size of a heap space for
999      recently created objects. If the command-line argument
1000      [`--max-semi-space-size`][] is set, it overrides this setting.
1001    * `codeRangeSizeMb` {number} The size of a pre-allocated memory range
1002      used for generated code.
1003    * `stackSizeMb` {number} The default maximum stack size for the thread.
1004      Small values may lead to unusable Worker instances. **Default:** `4`.
1005  * `name` {string} An optional `name` to be appended to the worker title
1006    for debugging/identification purposes, making the final title as
1007    `[worker ${id}] ${name}`. **Default:** `''`.
1008
1009### Event: `'error'`
1010
1011<!-- YAML
1012added: v10.5.0
1013-->
1014
1015* `err` {Error}
1016
1017The `'error'` event is emitted if the worker thread throws an uncaught
1018exception. In that case, the worker is terminated.
1019
1020### Event: `'exit'`
1021
1022<!-- YAML
1023added: v10.5.0
1024-->
1025
1026* `exitCode` {integer}
1027
1028The `'exit'` event is emitted once the worker has stopped. If the worker
1029exited by calling [`process.exit()`][], the `exitCode` parameter is the
1030passed exit code. If the worker was terminated, the `exitCode` parameter is
1031`1`.
1032
1033This is the final event emitted by any `Worker` instance.
1034
1035### Event: `'message'`
1036
1037<!-- YAML
1038added: v10.5.0
1039-->
1040
1041* `value` {any} The transmitted value
1042
1043The `'message'` event is emitted when the worker thread has invoked
1044[`require('node:worker_threads').parentPort.postMessage()`][].
1045See the [`port.on('message')`][] event for more details.
1046
1047All messages sent from the worker thread are emitted before the
1048[`'exit'` event][] is emitted on the `Worker` object.
1049
1050### Event: `'messageerror'`
1051
1052<!-- YAML
1053added:
1054  - v14.5.0
1055  - v12.19.0
1056-->
1057
1058* `error` {Error} An Error object
1059
1060The `'messageerror'` event is emitted when deserializing a message failed.
1061
1062### Event: `'online'`
1063
1064<!-- YAML
1065added: v10.5.0
1066-->
1067
1068The `'online'` event is emitted when the worker thread has started executing
1069JavaScript code.
1070
1071### `worker.getHeapSnapshot()`
1072
1073<!-- YAML
1074added:
1075 - v13.9.0
1076 - v12.17.0
1077-->
1078
1079* Returns: {Promise} A promise for a Readable Stream containing
1080  a V8 heap snapshot
1081
1082Returns a readable stream for a V8 snapshot of the current state of the Worker.
1083See [`v8.getHeapSnapshot()`][] for more details.
1084
1085If the Worker thread is no longer running, which may occur before the
1086[`'exit'` event][] is emitted, the returned `Promise` is rejected
1087immediately with an [`ERR_WORKER_NOT_RUNNING`][] error.
1088
1089### `worker.performance`
1090
1091<!-- YAML
1092added:
1093  - v15.1.0
1094  - v14.17.0
1095  - v12.22.0
1096-->
1097
1098An object that can be used to query performance information from a worker
1099instance. Similar to [`perf_hooks.performance`][].
1100
1101#### `performance.eventLoopUtilization([utilization1[, utilization2]])`
1102
1103<!-- YAML
1104added:
1105  - v15.1.0
1106  - v14.17.0
1107  - v12.22.0
1108-->
1109
1110* `utilization1` {Object} The result of a previous call to
1111  `eventLoopUtilization()`.
1112* `utilization2` {Object} The result of a previous call to
1113  `eventLoopUtilization()` prior to `utilization1`.
1114* Returns {Object}
1115  * `idle` {number}
1116  * `active` {number}
1117  * `utilization` {number}
1118
1119The same call as [`perf_hooks` `eventLoopUtilization()`][], except the values
1120of the worker instance are returned.
1121
1122One difference is that, unlike the main thread, bootstrapping within a worker
1123is done within the event loop. So the event loop utilization is
1124immediately available once the worker's script begins execution.
1125
1126An `idle` time that does not increase does not indicate that the worker is
1127stuck in bootstrap. The following examples shows how the worker's entire
1128lifetime never accumulates any `idle` time, but is still be able to process
1129messages.
1130
1131```js
1132const { Worker, isMainThread, parentPort } = require('node:worker_threads');
1133
1134if (isMainThread) {
1135  const worker = new Worker(__filename);
1136  setInterval(() => {
1137    worker.postMessage('hi');
1138    console.log(worker.performance.eventLoopUtilization());
1139  }, 100).unref();
1140  return;
1141}
1142
1143parentPort.on('message', () => console.log('msg')).unref();
1144(function r(n) {
1145  if (--n < 0) return;
1146  const t = Date.now();
1147  while (Date.now() - t < 300);
1148  setImmediate(r, n);
1149})(10);
1150```
1151
1152The event loop utilization of a worker is available only after the [`'online'`
1153event][] emitted, and if called before this, or after the [`'exit'`
1154event][], then all properties have the value of `0`.
1155
1156### `worker.postMessage(value[, transferList])`
1157
1158<!-- YAML
1159added: v10.5.0
1160-->
1161
1162* `value` {any}
1163* `transferList` {Object\[]}
1164
1165Send a message to the worker that is received via
1166[`require('node:worker_threads').parentPort.on('message')`][].
1167See [`port.postMessage()`][] for more details.
1168
1169### `worker.ref()`
1170
1171<!-- YAML
1172added: v10.5.0
1173-->
1174
1175Opposite of `unref()`, calling `ref()` on a previously `unref()`ed worker does
1176_not_ let the program exit if it's the only active handle left (the default
1177behavior). If the worker is `ref()`ed, calling `ref()` again has
1178no effect.
1179
1180### `worker.resourceLimits`
1181
1182<!-- YAML
1183added:
1184 - v13.2.0
1185 - v12.16.0
1186-->
1187
1188* {Object}
1189  * `maxYoungGenerationSizeMb` {number}
1190  * `maxOldGenerationSizeMb` {number}
1191  * `codeRangeSizeMb` {number}
1192  * `stackSizeMb` {number}
1193
1194Provides the set of JS engine resource constraints for this Worker thread.
1195If the `resourceLimits` option was passed to the [`Worker`][] constructor,
1196this matches its values.
1197
1198If the worker has stopped, the return value is an empty object.
1199
1200### `worker.stderr`
1201
1202<!-- YAML
1203added: v10.5.0
1204-->
1205
1206* {stream.Readable}
1207
1208This is a readable stream which contains data written to [`process.stderr`][]
1209inside the worker thread. If `stderr: true` was not passed to the
1210[`Worker`][] constructor, then data is piped to the parent thread's
1211[`process.stderr`][] stream.
1212
1213### `worker.stdin`
1214
1215<!-- YAML
1216added: v10.5.0
1217-->
1218
1219* {null|stream.Writable}
1220
1221If `stdin: true` was passed to the [`Worker`][] constructor, this is a
1222writable stream. The data written to this stream will be made available in
1223the worker thread as [`process.stdin`][].
1224
1225### `worker.stdout`
1226
1227<!-- YAML
1228added: v10.5.0
1229-->
1230
1231* {stream.Readable}
1232
1233This is a readable stream which contains data written to [`process.stdout`][]
1234inside the worker thread. If `stdout: true` was not passed to the
1235[`Worker`][] constructor, then data is piped to the parent thread's
1236[`process.stdout`][] stream.
1237
1238### `worker.terminate()`
1239
1240<!-- YAML
1241added: v10.5.0
1242changes:
1243  - version: v12.5.0
1244    pr-url: https://github.com/nodejs/node/pull/28021
1245    description: This function now returns a Promise.
1246                 Passing a callback is deprecated, and was useless up to this
1247                 version, as the Worker was actually terminated synchronously.
1248                 Terminating is now a fully asynchronous operation.
1249-->
1250
1251* Returns: {Promise}
1252
1253Stop all JavaScript execution in the worker thread as soon as possible.
1254Returns a Promise for the exit code that is fulfilled when the
1255[`'exit'` event][] is emitted.
1256
1257### `worker.threadId`
1258
1259<!-- YAML
1260added: v10.5.0
1261-->
1262
1263* {integer}
1264
1265An integer identifier for the referenced thread. Inside the worker thread,
1266it is available as [`require('node:worker_threads').threadId`][].
1267This value is unique for each `Worker` instance inside a single process.
1268
1269### `worker.unref()`
1270
1271<!-- YAML
1272added: v10.5.0
1273-->
1274
1275Calling `unref()` on a worker allows the thread to exit if this is the only
1276active handle in the event system. If the worker is already `unref()`ed calling
1277`unref()` again has no effect.
1278
1279## Notes
1280
1281### Synchronous blocking of stdio
1282
1283`Worker`s utilize message passing via {MessagePort} to implement interactions
1284with `stdio`. This means that `stdio` output originating from a `Worker` can
1285get blocked by synchronous code on the receiving end that is blocking the
1286Node.js event loop.
1287
1288```mjs
1289import {
1290  Worker,
1291  isMainThread,
1292} from 'worker_threads';
1293
1294if (isMainThread) {
1295  new Worker(new URL(import.meta.url));
1296  for (let n = 0; n < 1e10; n++) {
1297    // Looping to simulate work.
1298  }
1299} else {
1300  // This output will be blocked by the for loop in the main thread.
1301  console.log('foo');
1302}
1303```
1304
1305```cjs
1306'use strict';
1307
1308const {
1309  Worker,
1310  isMainThread,
1311} = require('node:worker_threads');
1312
1313if (isMainThread) {
1314  new Worker(__filename);
1315  for (let n = 0; n < 1e10; n++) {
1316    // Looping to simulate work.
1317  }
1318} else {
1319  // This output will be blocked by the for loop in the main thread.
1320  console.log('foo');
1321}
1322```
1323
1324### Launching worker threads from preload scripts
1325
1326Take care when launching worker threads from preload scripts (scripts loaded
1327and run using the `-r` command line flag). Unless the `execArgv` option is
1328explicitly set, new Worker threads automatically inherit the command line flags
1329from the running process and will preload the same preload scripts as the main
1330thread. If the preload script unconditionally launches a worker thread, every
1331thread spawned will spawn another until the application crashes.
1332
1333[Addons worker support]: addons.md#worker-support
1334[ECMAScript module loader]: esm.md#data-imports
1335[HTML structured clone algorithm]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
1336[Signals events]: process.md#signal-events
1337[Web Workers]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
1338[`'close'` event]: #event-close
1339[`'exit'` event]: #event-exit
1340[`'online'` event]: #event-online
1341[`--max-old-space-size`]: cli.md#--max-old-space-sizesize-in-megabytes
1342[`--max-semi-space-size`]: cli.md#--max-semi-space-sizesize-in-megabytes
1343[`ArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer
1344[`AsyncResource`]: async_hooks.md#class-asyncresource
1345[`Buffer.allocUnsafe()`]: buffer.md#static-method-bufferallocunsafesize
1346[`Buffer`]: buffer.md
1347[`ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST`]: errors.md#err_missing_message_port_in_transfer_list
1348[`ERR_WORKER_NOT_RUNNING`]: errors.md#err_worker_not_running
1349[`EventTarget`]: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget
1350[`FileHandle`]: fs.md#class-filehandle
1351[`MessagePort`]: #class-messageport
1352[`SharedArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer
1353[`Uint8Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array
1354[`WebAssembly.Module`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module
1355[`Worker constructor options`]: #new-workerfilename-options
1356[`Worker`]: #class-worker
1357[`data:` URL]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
1358[`fs.close()`]: fs.md#fsclosefd-callback
1359[`fs.open()`]: fs.md#fsopenpath-flags-mode-callback
1360[`markAsUntransferable()`]: #workermarkasuntransferableobject
1361[`node:cluster` module]: cluster.md
1362[`perf_hooks.performance`]: perf_hooks.md#perf_hooksperformance
1363[`perf_hooks` `eventLoopUtilization()`]: perf_hooks.md#performanceeventlooputilizationutilization1-utilization2
1364[`port.on('message')`]: #event-message
1365[`port.onmessage()`]: https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/onmessage
1366[`port.postMessage()`]: #portpostmessagevalue-transferlist
1367[`process.abort()`]: process.md#processabort
1368[`process.chdir()`]: process.md#processchdirdirectory
1369[`process.env`]: process.md#processenv
1370[`process.execArgv`]: process.md#processexecargv
1371[`process.exit()`]: process.md#processexitcode
1372[`process.stderr`]: process.md#processstderr
1373[`process.stdin`]: process.md#processstdin
1374[`process.stdout`]: process.md#processstdout
1375[`process.title`]: process.md#processtitle
1376[`require('node:worker_threads').isMainThread`]: #workerismainthread
1377[`require('node:worker_threads').parentPort.on('message')`]: #event-message
1378[`require('node:worker_threads').parentPort.postMessage()`]: #workerpostmessagevalue-transferlist
1379[`require('node:worker_threads').parentPort`]: #workerparentport
1380[`require('node:worker_threads').threadId`]: #workerthreadid
1381[`require('node:worker_threads').workerData`]: #workerworkerdata
1382[`trace_events`]: tracing.md
1383[`v8.getHeapSnapshot()`]: v8.md#v8getheapsnapshot
1384[`vm`]: vm.md
1385[`worker.SHARE_ENV`]: #workershare_env
1386[`worker.on('message')`]: #event-message_1
1387[`worker.postMessage()`]: #workerpostmessagevalue-transferlist
1388[`worker.terminate()`]: #workerterminate
1389[`worker.threadId`]: #workerthreadid_1
1390[async-resource-worker-pool]: async_context.md#using-asyncresource-for-a-worker-thread-pool
1391[browser `MessagePort`]: https://developer.mozilla.org/en-US/docs/Web/API/MessagePort
1392[child processes]: child_process.md
1393[contextified]: vm.md#what-does-it-mean-to-contextify-an-object
1394[v8.serdes]: v8.md#serialization-api
1395