Node.js v24.2.0 documentation
- Node.js v24.2.0
-
Table of contents
- Worker threads
worker.getEnvironmentData(key)
worker.isInternalThread
worker.isMainThread
worker.markAsUntransferable(object)
worker.isMarkedAsUntransferable(object)
worker.markAsUncloneable(object)
worker.moveMessagePortToContext(port, contextifiedSandbox)
worker.parentPort
worker.postMessageToThread(threadId, value[, transferList][, timeout])
worker.receiveMessageOnPort(port)
worker.resourceLimits
worker.SHARE_ENV
worker.setEnvironmentData(key[, value])
worker.threadId
worker.workerData
- Class:
BroadcastChannel extends EventTarget
- Class:
MessageChannel
- Class:
MessagePort
- Class:
Worker
new Worker(filename[, options])
- Event:
'error'
- Event:
'exit'
- Event:
'message'
- Event:
'messageerror'
- Event:
'online'
worker.getHeapSnapshot([options])
worker.getHeapStatistics()
worker.performance
worker.postMessage(value[, transferList])
worker.ref()
worker.resourceLimits
worker.stderr
worker.stdin
worker.stdout
worker.terminate()
worker.threadId
worker.unref()
worker[Symbol.asyncDispose]()
- Notes
- Worker threads
-
Index
- Assertion testing
- Asynchronous context tracking
- Async hooks
- Buffer
- C++ addons
- C/C++ addons with Node-API
- C++ embedder API
- Child processes
- Cluster
- Command-line options
- Console
- Crypto
- Debugger
- Deprecated APIs
- Diagnostics Channel
- DNS
- Domain
- Errors
- Events
- File system
- Globals
- HTTP
- HTTP/2
- HTTPS
- Inspector
- Internationalization
- Modules: CommonJS modules
- Modules: ECMAScript modules
- Modules:
node:module
API - Modules: Packages
- Modules: TypeScript
- Net
- OS
- Path
- Performance hooks
- Permissions
- Process
- Punycode
- Query strings
- Readline
- REPL
- Report
- Single executable applications
- SQLite
- Stream
- String decoder
- Test runner
- Timers
- TLS/SSL
- Trace events
- TTY
- UDP/datagram
- URL
- Utilities
- V8
- VM
- WASI
- Web Crypto API
- Web Streams API
- Worker threads
- Zlib
- Other versions
- Options
Worker threads#
Source Code: lib/worker_threads.js
The node:worker_threads
module enables the use of threads that execute
JavaScript in parallel. To access it:
import worker from 'node:worker_threads';
'use strict';
const worker = require('node:worker_threads');
Workers (threads) are useful for performing CPU-intensive JavaScript operations. They do not help much with I/O-intensive work. The Node.js built-in asynchronous I/O operations are more efficient than Workers can be.
Unlike child_process
or cluster
, worker_threads
can share memory. They do
so by transferring ArrayBuffer
instances or sharing SharedArrayBuffer
instances.
import {
Worker,
isMainThread,
parentPort,
workerData,
} from 'node:worker_threads';
if (!isMainThread) {
const { parse } = await import('some-js-parsing-library');
const script = workerData;
parentPort.postMessage(parse(script));
}
export default function parseJSAsync(script) {
return new Promise((resolve, reject) => {
const worker = new Worker(new URL(import.meta.url), {
workerData: script,
});
worker.on('message', resolve);
worker.on('error', reject);
worker.on('exit', (code) => {
if (code !== 0)
reject(new Error(`Worker stopped with exit code ${code}`));
});
});
};
'use strict';
const {
Worker,
isMainThread,
parentPort,
workerData,
} = require('node:worker_threads');
if (isMainThread) {
module.exports = function parseJSAsync(script) {
return new Promise((resolve, reject) => {
const worker = new Worker(__filename, {
workerData: script,
});
worker.on('message', resolve);
worker.on('error', reject);
worker.on('exit', (code) => {
if (code !== 0)
reject(new Error(`Worker stopped with exit code ${code}`));
});
});
};
} else {
const { parse } = require('some-js-parsing-library');
const script = workerData;
parentPort.postMessage(parse(script));
}
The above example spawns a Worker thread for each parseJSAsync()
call. In
practice, use a pool of Workers for these kinds of tasks. Otherwise, the
overhead of creating Workers would likely exceed their benefit.
When implementing a worker pool, use the AsyncResource
API to inform
diagnostic tools (e.g. to provide asynchronous stack traces) about the
correlation between tasks and their outcomes. See
"Using AsyncResource
for a Worker
thread pool"
in the async_hooks
documentation for an example implementation.
Worker threads inherit non-process-specific options by default. Refer to
Worker constructor options
to know how to customize worker thread options,
specifically argv
and execArgv
options.
worker.getEnvironmentData(key)
#
Within a worker thread, worker.getEnvironmentData()
returns a clone
of data passed to the spawning thread's worker.setEnvironmentData()
.
Every new Worker
receives its own copy of the environment data
automatically.
import {
Worker,
isMainThread,
setEnvironmentData,
getEnvironmentData,
} from 'node:worker_threads';
if (isMainThread) {
setEnvironmentData('Hello', 'World!');
const worker = new Worker(new URL(import.meta.url));
} else {
console.log(getEnvironmentData('Hello')); // Prints 'World!'.
}
'use strict';
const {
Worker,
isMainThread,
setEnvironmentData,
getEnvironmentData,
} = require('node:worker_threads');
if (isMainThread) {
setEnvironmentData('Hello', 'World!');
const worker = new Worker(__filename);
} else {
console.log(getEnvironmentData('Hello')); // Prints 'World!'.
}
worker.isInternalThread
#
Is true
if this code is running inside of an internal Worker
thread (e.g the loader thread).
node --experimental-loader ./loader.js main.js
// loader.js
import { isInternalThread } from 'node:worker_threads';
console.log(isInternalThread); // true
// loader.js
'use strict';
const { isInternalThread } = require('node:worker_threads');
console.log(isInternalThread); // true
// main.js
import { isInternalThread } from 'node:worker_threads';
console.log(isInternalThread); // false
// main.js
'use strict';
const { isInternalThread } = require('node:worker_threads');
console.log(isInternalThread); // false
worker.isMainThread
#
Is true
if this code is not running inside of a Worker
thread.
import { Worker, isMainThread } from 'node:worker_threads';
if (isMainThread) {
// This re-loads the current file inside a Worker instance.
new Worker(new URL(import.meta.url));
} else {
console.log('Inside Worker!');
console.log(isMainThread); // Prints 'false'.
}
'use strict';
const { Worker, isMainThread } = require('node:worker_threads');
if (isMainThread) {
// This re-loads the current file inside a Worker instance.
new Worker(__filename);
} else {
console.log('Inside Worker!');
console.log(isMainThread); // Prints 'false'.
}
worker.markAsUntransferable(object)
#
object
<any> Any arbitrary JavaScript value.
Mark an object as not transferable. If object
occurs in the transfer list of
a port.postMessage()
call, an error is thrown. This is a no-op if
object
is a primitive value.
In particular, this makes sense for objects that can be cloned, rather than
transferred, and which are used by other objects on the sending side.
For example, Node.js marks the ArrayBuffer
s it uses for its
Buffer
pool with this.
This operation cannot be undone.
import { MessageChannel, markAsUntransferable } from 'node:worker_threads';
const pooledBuffer = new ArrayBuffer(8);
const typedArray1 = new Uint8Array(pooledBuffer);
const typedArray2 = new Float64Array(pooledBuffer);
markAsUntransferable(pooledBuffer);
const { port1 } = new MessageChannel();
try {
// This will throw an error, because pooledBuffer is not transferable.
port1.postMessage(typedArray1, [ typedArray1.buffer ]);
} catch (error) {
// error.name === 'DataCloneError'
}
// The following line prints the contents of typedArray1 -- it still owns
// its memory and has not been transferred. Without
// `markAsUntransferable()`, this would print an empty Uint8Array and the
// postMessage call would have succeeded.
// typedArray2 is intact as well.
console.log(typedArray1);
console.log(typedArray2);
'use strict';
const { MessageChannel, markAsUntransferable } = require('node:worker_threads');
const pooledBuffer = new ArrayBuffer(8);
const typedArray1 = new Uint8Array(pooledBuffer);
const typedArray2 = new Float64Array(pooledBuffer);
markAsUntransferable(pooledBuffer);
const { port1 } = new MessageChannel();
try {
// This will throw an error, because pooledBuffer is not transferable.
port1.postMessage(typedArray1, [ typedArray1.buffer ]);
} catch (error) {
// error.name === 'DataCloneError'
}
// The following line prints the contents of typedArray1 -- it still owns
// its memory and has not been transferred. Without
// `markAsUntransferable()`, this would print an empty Uint8Array and the
// postMessage call would have succeeded.
// typedArray2 is intact as well.
console.log(typedArray1);
console.log(typedArray2);
There is no equivalent to this API in browsers.
worker.isMarkedAsUntransferable(object)
#
Check if an object is marked as not transferable with
markAsUntransferable()
.
import { markAsUntransferable, isMarkedAsUntransferable } from 'node:worker_threads';
const pooledBuffer = new ArrayBuffer(8);
markAsUntransferable(pooledBuffer);
isMarkedAsUntransferable(pooledBuffer); // Returns true.
'use strict';
const { markAsUntransferable, isMarkedAsUntransferable } = require('node:worker_threads');
const pooledBuffer = new ArrayBuffer(8);
markAsUntransferable(pooledBuffer);
isMarkedAsUntransferable(pooledBuffer); // Returns true.
There is no equivalent to this API in browsers.
worker.markAsUncloneable(object)
#
object
<any> Any arbitrary JavaScript value.
Mark an object as not cloneable. If object
is used as message
in
a port.postMessage()
call, an error is thrown. This is a no-op if object
is a
primitive value.
This has no effect on ArrayBuffer
, or any Buffer
like objects.
This operation cannot be undone.
import { markAsUncloneable } from 'node:worker_threads';
const anyObject = { foo: 'bar' };
markAsUncloneable(anyObject);
const { port1 } = new MessageChannel();
try {
// This will throw an error, because anyObject is not cloneable.
port1.postMessage(anyObject);
} catch (error) {
// error.name === 'DataCloneError'
}
'use strict';
const { markAsUncloneable } = require('node:worker_threads');
const anyObject = { foo: 'bar' };
markAsUncloneable(anyObject);
const { port1 } = new MessageChannel();
try {
// This will throw an error, because anyObject is not cloneable.
port1.postMessage(anyObject);
} catch (error) {
// error.name === 'DataCloneError'
}
There is no equivalent to this API in browsers.
worker.moveMessagePortToContext(port, contextifiedSandbox)
#
-
port
<MessagePort> The message port to transfer. -
contextifiedSandbox
<Object> A contextified object as returned by thevm.createContext()
method. -
Returns: <MessagePort>
Transfer a MessagePort
to a different vm
Context. The original port
object is rendered unusable, and the returned MessagePort
instance
takes its place.
The returned MessagePort
is an object in the target context and
inherits from its global Object
class. Objects passed to the
port.onmessage()
listener are also created in the target context
and inherit from its global Object
class.
However, the created MessagePort
no longer inherits from
<EventTarget>, and only port.onmessage()
can be used to receive
events using it.
worker.parentPort
#
If this thread is a Worker
, this is a MessagePort
allowing communication with the parent thread. Messages sent using
parentPort.postMessage()
are available in the parent thread
using worker.on('message')
, and messages sent from the parent thread
using worker.postMessage()
are available in this thread using
parentPort.on('message')
.
import { Worker, isMainThread, parentPort } from 'node:worker_threads';
if (isMainThread) {
const worker = new Worker(new URL(import.meta.url));
worker.once('message', (message) => {
console.log(message); // Prints 'Hello, world!'.
});
worker.postMessage('Hello, world!');
} else {
// When a message from the parent thread is received, send it back:
parentPort.once('message', (message) => {
parentPort.postMessage(message);
});
}
'use strict';
const { Worker, isMainThread, parentPort } = require('node:worker_threads');
if (isMainThread) {
const worker = new Worker(__filename);
worker.once('message', (message) => {
console.log(message); // Prints 'Hello, world!'.
});
worker.postMessage('Hello, world!');
} else {
// When a message from the parent thread is received, send it back:
parentPort.once('message', (message) => {
parentPort.postMessage(message);
});
}
worker.postMessageToThread(threadId, value[, transferList][, timeout])
#
threadId
<number> The target thread ID. If the thread ID is invalid, aERR_WORKER_MESSAGING_FAILED
error will be thrown. If the target thread ID is the current thread ID, aERR_WORKER_MESSAGING_SAME_THREAD
error will be thrown.value
<any> The value to send.transferList
<Object[]> If one or moreMessagePort
-like objects are passed invalue
, atransferList
is required for those items or