• 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). On Windows, unlike the main thread, a copy of the
848  environment variables operates in a case-sensitive manner.
849* [`process.title`][] cannot be modified.
850* Signals are not delivered through [`process.on('...')`][Signals events].
851* Execution may stop at any point as a result of [`worker.terminate()`][]
852  being invoked.
853* IPC channels from parent processes are not accessible.
854* The [`trace_events`][] module is not supported.
855* Native add-ons can only be loaded from multiple threads if they fulfill
856  [certain conditions][Addons worker support].
857
858Creating `Worker` instances inside of other `Worker`s is possible.
859
860Like [Web Workers][] and the [`node:cluster` module][], two-way communication
861can be achieved through inter-thread message passing. Internally, a `Worker` has
862a built-in pair of [`MessagePort`][]s that are already associated with each
863other when the `Worker` is created. While the `MessagePort` object on the parent
864side is not directly exposed, its functionalities are exposed through
865[`worker.postMessage()`][] and the [`worker.on('message')`][] event
866on the `Worker` object for the parent thread.
867
868To create custom messaging channels (which is encouraged over using the default
869global channel because it facilitates separation of concerns), users can create
870a `MessageChannel` object on either thread and pass one of the
871`MessagePort`s on that `MessageChannel` to the other thread through a
872pre-existing channel, such as the global one.
873
874See [`port.postMessage()`][] for more information on how messages are passed,
875and what kind of JavaScript values can be successfully transported through
876the thread barrier.
877
878```js
879const assert = require('node:assert');
880const {
881  Worker, MessageChannel, MessagePort, isMainThread, parentPort,
882} = require('node:worker_threads');
883if (isMainThread) {
884  const worker = new Worker(__filename);
885  const subChannel = new MessageChannel();
886  worker.postMessage({ hereIsYourPort: subChannel.port1 }, [subChannel.port1]);
887  subChannel.port2.on('message', (value) => {
888    console.log('received:', value);
889  });
890} else {
891  parentPort.once('message', (value) => {
892    assert(value.hereIsYourPort instanceof MessagePort);
893    value.hereIsYourPort.postMessage('the worker is sending this');
894    value.hereIsYourPort.close();
895  });
896}
897```
898
899### `new Worker(filename[, options])`
900
901<!-- YAML
902added: v10.5.0
903changes:
904  - version: v18.16.0
905    pr-url: https://github.com/nodejs/node/pull/46832
906    description: Added support for a `name` option, which allows
907                 adding a name to worker title for debugging.
908  - version: v14.9.0
909    pr-url: https://github.com/nodejs/node/pull/34584
910    description: The `filename` parameter can be a WHATWG `URL` object using
911                 `data:` protocol.
912  - version: v14.9.0
913    pr-url: https://github.com/nodejs/node/pull/34394
914    description: The `trackUnmanagedFds` option was set to `true` by default.
915  - version:
916    - v14.6.0
917    - v12.19.0
918    pr-url: https://github.com/nodejs/node/pull/34303
919    description: The `trackUnmanagedFds` option was introduced.
920  - version:
921     - v13.13.0
922     - v12.17.0
923    pr-url: https://github.com/nodejs/node/pull/32278
924    description: The `transferList` option was introduced.
925  - version:
926     - v13.12.0
927     - v12.17.0
928    pr-url: https://github.com/nodejs/node/pull/31664
929    description: The `filename` parameter can be a WHATWG `URL` object using
930                 `file:` protocol.
931  - version:
932     - v13.4.0
933     - v12.16.0
934    pr-url: https://github.com/nodejs/node/pull/30559
935    description: The `argv` option was introduced.
936  - version:
937     - v13.2.0
938     - v12.16.0
939    pr-url: https://github.com/nodejs/node/pull/26628
940    description: The `resourceLimits` option was introduced.
941-->
942
943* `filename` {string|URL} The path to the Worker's main script or module. Must
944  be either an absolute path or a relative path (i.e. relative to the
945  current working directory) starting with `./` or `../`, or a WHATWG `URL`
946  object using `file:` or `data:` protocol.
947  When using a [`data:` URL][], the data is interpreted based on MIME type using
948  the [ECMAScript module loader][].
949  If `options.eval` is `true`, this is a string containing JavaScript code
950  rather than a path.
951* `options` {Object}
952  * `argv` {any\[]} List of arguments which would be stringified and appended to
953    `process.argv` in the worker. This is mostly similar to the `workerData`
954    but the values are available on the global `process.argv` as if they
955    were passed as CLI options to the script.
956  * `env` {Object} If set, specifies the initial value of `process.env` inside
957    the Worker thread. As a special value, [`worker.SHARE_ENV`][] may be used
958    to specify that the parent thread and the child thread should share their
959    environment variables; in that case, changes to one thread's `process.env`
960    object affect the other thread as well. **Default:** `process.env`.
961  * `eval` {boolean} If `true` and the first argument is a `string`, interpret
962    the first argument to the constructor as a script that is executed once the
963    worker is online.
964  * `execArgv` {string\[]} List of node CLI options passed to the worker.
965    V8 options (such as `--max-old-space-size`) and options that affect the
966    process (such as `--title`) are not supported. If set, this is provided
967    as [`process.execArgv`][] inside the worker. By default, options are
968    inherited from the parent thread.
969  * `stdin` {boolean} If this is set to `true`, then `worker.stdin`
970    provides a writable stream whose contents appear as `process.stdin`
971    inside the Worker. By default, no data is provided.
972  * `stdout` {boolean} If this is set to `true`, then `worker.stdout` is
973    not automatically piped through to `process.stdout` in the parent.
974  * `stderr` {boolean} If this is set to `true`, then `worker.stderr` is
975    not automatically piped through to `process.stderr` in the parent.
976  * `workerData` {any} Any JavaScript value that is cloned and made
977    available as [`require('node:worker_threads').workerData`][]. The cloning
978    occurs as described in the [HTML structured clone algorithm][], and an error
979    is thrown if the object cannot be cloned (e.g. because it contains
980    `function`s).
981  * `trackUnmanagedFds` {boolean} If this is set to `true`, then the Worker
982    tracks raw file descriptors managed through [`fs.open()`][] and
983    [`fs.close()`][], and closes them when the Worker exits, similar to other
984    resources like network sockets or file descriptors managed through
985    the [`FileHandle`][] API. This option is automatically inherited by all
986    nested `Worker`s. **Default:** `true`.
987  * `transferList` {Object\[]} If one or more `MessagePort`-like objects
988    are passed in `workerData`, a `transferList` is required for those
989    items or [`ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST`][] is thrown.
990    See [`port.postMessage()`][] for more information.
991  * `resourceLimits` {Object} An optional set of resource limits for the new JS
992    engine instance. Reaching these limits leads to termination of the `Worker`
993    instance. These limits only affect the JS engine, and no external data,
994    including no `ArrayBuffer`s. Even if these limits are set, the process may
995    still abort if it encounters a global out-of-memory situation.
996    * `maxOldGenerationSizeMb` {number} The maximum size of the main heap in
997      MB. If the command-line argument [`--max-old-space-size`][] is set, it
998      overrides this setting.
999    * `maxYoungGenerationSizeMb` {number} The maximum size of a heap space for
1000      recently created objects. If the command-line argument
1001      [`--max-semi-space-size`][] is set, it overrides this setting.
1002    * `codeRangeSizeMb` {number} The size of a pre-allocated memory range
1003      used for generated code.
1004    * `stackSizeMb` {number} The default maximum stack size for the thread.
1005      Small values may lead to unusable Worker instances. **Default:** `4`.
1006  * `name` {string} An optional `name` to be appended to the worker title
1007    for debugging/identification purposes, making the final title as
1008    `[worker ${id}] ${name}`. **Default:** `''`.
1009
1010### Event: `'error'`
1011
1012<!-- YAML
1013added: v10.5.0
1014-->
1015
1016* `err` {Error}
1017
1018The `'error'` event is emitted if the worker thread throws an uncaught
1019exception. In that case, the worker is terminated.
1020
1021### Event: `'exit'`
1022
1023<!-- YAML
1024added: v10.5.0
1025-->
1026
1027* `exitCode` {integer}
1028
1029The `'exit'` event is emitted once the worker has stopped. If the worker
1030exited by calling [`process.exit()`][], the `exitCode` parameter is the
1031passed exit code. If the worker was terminated, the `exitCode` parameter is
1032`1`.
1033
1034This is the final event emitted by any `Worker` instance.
1035
1036### Event: `'message'`
1037
1038<!-- YAML
1039added: v10.5.0
1040-->
1041
1042* `value` {any} The transmitted value
1043
1044The `'message'` event is emitted when the worker thread has invoked
1045[`require('node:worker_threads').parentPort.postMessage()`][].
1046See the [`port.on('message')`][] event for more details.
1047
1048All messages sent from the worker thread are emitted before the
1049[`'exit'` event][] is emitted on the `Worker` object.
1050
1051### Event: `'messageerror'`
1052
1053<!-- YAML
1054added:
1055  - v14.5.0
1056  - v12.19.0
1057-->
1058
1059* `error` {Error} An Error object
1060
1061The `'messageerror'` event is emitted when deserializing a message failed.
1062
1063### Event: `'online'`
1064
1065<!-- YAML
1066added: v10.5.0
1067-->
1068
1069The `'online'` event is emitted when the worker thread has started executing
1070JavaScript code.
1071
1072### `worker.getHeapSnapshot()`
1073
1074<!-- YAML
1075added:
1076 - v13.9.0
1077 - v12.17.0
1078-->
1079
1080* Returns: {Promise} A promise for a Readable Stream containing
1081  a V8 heap snapshot
1082
1083Returns a readable stream for a V8 snapshot of the current state of the Worker.
1084See [`v8.getHeapSnapshot()`][] for more details.
1085
1086If the Worker thread is no longer running, which may occur before the
1087[`'exit'` event][] is emitted, the returned `Promise` is rejected
1088immediately with an [`ERR_WORKER_NOT_RUNNING`][] error.
1089
1090### `worker.performance`
1091
1092<!-- YAML
1093added:
1094  - v15.1.0
1095  - v14.17.0
1096  - v12.22.0
1097-->
1098
1099An object that can be used to query performance information from a worker
1100instance. Similar to [`perf_hooks.performance`][].
1101
1102#### `performance.eventLoopUtilization([utilization1[, utilization2]])`
1103
1104<!-- YAML
1105added:
1106  - v15.1.0
1107  - v14.17.0
1108  - v12.22.0
1109-->
1110
1111* `utilization1` {Object} The result of a previous call to
1112  `eventLoopUtilization()`.
1113* `utilization2` {Object} The result of a previous call to
1114  `eventLoopUtilization()` prior to `utilization1`.
1115* Returns {Object}
1116  * `idle` {number}
1117  * `active` {number}
1118  * `utilization` {number}
1119
1120The same call as [`perf_hooks` `eventLoopUtilization()`][], except the values
1121of the worker instance are returned.
1122
1123One difference is that, unlike the main thread, bootstrapping within a worker
1124is done within the event loop. So the event loop utilization is
1125immediately available once the worker's script begins execution.
1126
1127An `idle` time that does not increase does not indicate that the worker is
1128stuck in bootstrap. The following examples shows how the worker's entire
1129lifetime never accumulates any `idle` time, but is still be able to process
1130messages.
1131
1132```js
1133const { Worker, isMainThread, parentPort } = require('node:worker_threads');
1134
1135if (isMainThread) {
1136  const worker = new Worker(__filename);
1137  setInterval(() => {
1138    worker.postMessage('hi');
1139    console.log(worker.performance.eventLoopUtilization());
1140  }, 100).unref();
1141  return;
1142}
1143
1144parentPort.on('message', () => console.log('msg')).unref();
1145(function r(n) {
1146  if (--n < 0) return;
1147  const t = Date.now();
1148  while (Date.now() - t < 300);
1149  setImmediate(r, n);
1150})(10);
1151```
1152
1153The event loop utilization of a worker is available only after the [`'online'`
1154event][] emitted, and if called before this, or after the [`'exit'`
1155event][], then all properties have the value of `0`.
1156
1157### `worker.postMessage(value[, transferList])`
1158
1159<!-- YAML
1160added: v10.5.0
1161-->
1162
1163* `value` {any}
1164* `transferList` {Object\[]}
1165
1166Send a message to the worker that is received via
1167[`require('node:worker_threads').parentPort.on('message')`][].
1168See [`port.postMessage()`][] for more details.
1169
1170### `worker.ref()`
1171
1172<!-- YAML
1173added: v10.5.0
1174-->
1175
1176Opposite of `unref()`, calling `ref()` on a previously `unref()`ed worker does
1177_not_ let the program exit if it's the only active handle left (the default
1178behavior). If the worker is `ref()`ed, calling `ref()` again has
1179no effect.
1180
1181### `worker.resourceLimits`
1182
1183<!-- YAML
1184added:
1185 - v13.2.0
1186 - v12.16.0
1187-->
1188
1189* {Object}
1190  * `maxYoungGenerationSizeMb` {number}
1191  * `maxOldGenerationSizeMb` {number}
1192  * `codeRangeSizeMb` {number}
1193  * `stackSizeMb` {number}
1194
1195Provides the set of JS engine resource constraints for this Worker thread.
1196If the `resourceLimits` option was passed to the [`Worker`][] constructor,
1197this matches its values.
1198
1199If the worker has stopped, the return value is an empty object.
1200
1201### `worker.stderr`
1202
1203<!-- YAML
1204added: v10.5.0
1205-->
1206
1207* {stream.Readable}
1208
1209This is a readable stream which contains data written to [`process.stderr`][]
1210inside the worker thread. If `stderr: true` was not passed to the
1211[`Worker`][] constructor, then data is piped to the parent thread's
1212[`process.stderr`][] stream.
1213
1214### `worker.stdin`
1215
1216<!-- YAML
1217added: v10.5.0
1218-->
1219
1220* {null|stream.Writable}
1221
1222If `stdin: true` was passed to the [`Worker`][] constructor, this is a
1223writable stream. The data written to this stream will be made available in
1224the worker thread as [`process.stdin`][].
1225
1226### `worker.stdout`
1227
1228<!-- YAML
1229added: v10.5.0
1230-->
1231
1232* {stream.Readable}
1233
1234This is a readable stream which contains data written to [`process.stdout`][]
1235inside the worker thread. If `stdout: true` was not passed to the
1236[`Worker`][] constructor, then data is piped to the parent thread's
1237[`process.stdout`][] stream.
1238
1239### `worker.terminate()`
1240
1241<!-- YAML
1242added: v10.5.0
1243changes:
1244  - version: v12.5.0
1245    pr-url: https://github.com/nodejs/node/pull/28021
1246    description: This function now returns a Promise.
1247                 Passing a callback is deprecated, and was useless up to this
1248                 version, as the Worker was actually terminated synchronously.
1249                 Terminating is now a fully asynchronous operation.
1250-->
1251
1252* Returns: {Promise}
1253
1254Stop all JavaScript execution in the worker thread as soon as possible.
1255Returns a Promise for the exit code that is fulfilled when the
1256[`'exit'` event][] is emitted.
1257
1258### `worker.threadId`
1259
1260<!-- YAML
1261added: v10.5.0
1262-->
1263
1264* {integer}
1265
1266An integer identifier for the referenced thread. Inside the worker thread,
1267it is available as [`require('node:worker_threads').threadId`][].
1268This value is unique for each `Worker` instance inside a single process.
1269
1270### `worker.unref()`
1271
1272<!-- YAML
1273added: v10.5.0
1274-->
1275
1276Calling `unref()` on a worker allows the thread to exit if this is the only
1277active handle in the event system. If the worker is already `unref()`ed calling
1278`unref()` again has no effect.
1279
1280## Notes
1281
1282### Synchronous blocking of stdio
1283
1284`Worker`s utilize message passing via {MessagePort} to implement interactions
1285with `stdio`. This means that `stdio` output originating from a `Worker` can
1286get blocked by synchronous code on the receiving end that is blocking the
1287Node.js event loop.
1288
1289```mjs
1290import {
1291  Worker,
1292  isMainThread,
1293} from 'worker_threads';
1294
1295if (isMainThread) {
1296  new Worker(new URL(import.meta.url));
1297  for (let n = 0; n < 1e10; n++) {
1298    // Looping to simulate work.
1299  }
1300} else {
1301  // This output will be blocked by the for loop in the main thread.
1302  console.log('foo');
1303}
1304```
1305
1306```cjs
1307'use strict';
1308
1309const {
1310  Worker,
1311  isMainThread,
1312} = require('node:worker_threads');
1313
1314if (isMainThread) {
1315  new Worker(__filename);
1316  for (let n = 0; n < 1e10; n++) {
1317    // Looping to simulate work.
1318  }
1319} else {
1320  // This output will be blocked by the for loop in the main thread.
1321  console.log('foo');
1322}
1323```
1324
1325### Launching worker threads from preload scripts
1326
1327Take care when launching worker threads from preload scripts (scripts loaded
1328and run using the `-r` command line flag). Unless the `execArgv` option is
1329explicitly set, new Worker threads automatically inherit the command line flags
1330from the running process and will preload the same preload scripts as the main
1331thread. If the preload script unconditionally launches a worker thread, every
1332thread spawned will spawn another until the application crashes.
1333
1334[Addons worker support]: addons.md#worker-support
1335[ECMAScript module loader]: esm.md#data-imports
1336[HTML structured clone algorithm]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
1337[Signals events]: process.md#signal-events
1338[Web Workers]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
1339[`'close'` event]: #event-close
1340[`'exit'` event]: #event-exit
1341[`'online'` event]: #event-online
1342[`--max-old-space-size`]: cli.md#--max-old-space-sizesize-in-megabytes
1343[`--max-semi-space-size`]: cli.md#--max-semi-space-sizesize-in-megabytes
1344[`ArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer
1345[`AsyncResource`]: async_hooks.md#class-asyncresource
1346[`Buffer.allocUnsafe()`]: buffer.md#static-method-bufferallocunsafesize
1347[`Buffer`]: buffer.md
1348[`ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST`]: errors.md#err_missing_message_port_in_transfer_list
1349[`ERR_WORKER_NOT_RUNNING`]: errors.md#err_worker_not_running
1350[`EventTarget`]: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget
1351[`FileHandle`]: fs.md#class-filehandle
1352[`MessagePort`]: #class-messageport
1353[`SharedArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer
1354[`Uint8Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array
1355[`WebAssembly.Module`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module
1356[`Worker constructor options`]: #new-workerfilename-options
1357[`Worker`]: #class-worker
1358[`data:` URL]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
1359[`fs.close()`]: fs.md#fsclosefd-callback
1360[`fs.open()`]: fs.md#fsopenpath-flags-mode-callback
1361[`markAsUntransferable()`]: #workermarkasuntransferableobject
1362[`node:cluster` module]: cluster.md
1363[`perf_hooks.performance`]: perf_hooks.md#perf_hooksperformance
1364[`perf_hooks` `eventLoopUtilization()`]: perf_hooks.md#performanceeventlooputilizationutilization1-utilization2
1365[`port.on('message')`]: #event-message
1366[`port.onmessage()`]: https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/onmessage
1367[`port.postMessage()`]: #portpostmessagevalue-transferlist
1368[`process.abort()`]: process.md#processabort
1369[`process.chdir()`]: process.md#processchdirdirectory
1370[`process.env`]: process.md#processenv
1371[`process.execArgv`]: process.md#processexecargv
1372[`process.exit()`]: process.md#processexitcode
1373[`process.stderr`]: process.md#processstderr
1374[`process.stdin`]: process.md#processstdin
1375[`process.stdout`]: process.md#processstdout
1376[`process.title`]: process.md#processtitle
1377[`require('node:worker_threads').isMainThread`]: #workerismainthread
1378[`require('node:worker_threads').parentPort.on('message')`]: #event-message
1379[`require('node:worker_threads').parentPort.postMessage()`]: #workerpostmessagevalue-transferlist
1380[`require('node:worker_threads').parentPort`]: #workerparentport
1381[`require('node:worker_threads').threadId`]: #workerthreadid
1382[`require('node:worker_threads').workerData`]: #workerworkerdata
1383[`trace_events`]: tracing.md
1384[`v8.getHeapSnapshot()`]: v8.md#v8getheapsnapshot
1385[`vm`]: vm.md
1386[`worker.SHARE_ENV`]: #workershare_env
1387[`worker.on('message')`]: #event-message_1
1388[`worker.postMessage()`]: #workerpostmessagevalue-transferlist
1389[`worker.terminate()`]: #workerterminate
1390[`worker.threadId`]: #workerthreadid_1
1391[async-resource-worker-pool]: async_context.md#using-asyncresource-for-a-worker-thread-pool
1392[browser `MessagePort`]: https://developer.mozilla.org/en-US/docs/Web/API/MessagePort
1393[child processes]: child_process.md
1394[contextified]: vm.md#what-does-it-mean-to-contextify-an-object
1395[v8.serdes]: v8.md#serialization-api
1396