2018-06-01 15:13:43 +02:00
|
|
|
|
# Worker Threads
|
2017-09-05 22:38:32 +02:00
|
|
|
|
|
2018-06-19 09:35:50 +02:00
|
|
|
|
<!--introduced_in=v10.5.0-->
|
2017-09-05 22:38:32 +02:00
|
|
|
|
|
2019-09-09 22:34:30 +02:00
|
|
|
|
> Stability: 2 - Stable
|
2017-09-05 22:38:32 +02:00
|
|
|
|
|
2019-03-22 22:41:29 +01:00
|
|
|
|
The `worker_threads` module enables the use of threads that execute JavaScript
|
2019-02-14 22:10:03 +01:00
|
|
|
|
in parallel. To access it:
|
2017-09-01 17:03:41 +02:00
|
|
|
|
|
|
|
|
|
```js
|
2018-06-01 15:13:43 +02:00
|
|
|
|
const worker = require('worker_threads');
|
2017-09-01 17:03:41 +02:00
|
|
|
|
```
|
|
|
|
|
|
2019-01-09 00:18:19 +01:00
|
|
|
|
Workers (threads) are useful for performing CPU-intensive JavaScript operations.
|
|
|
|
|
They will not help much with I/O-intensive work. Node.js’s built-in asynchronous
|
|
|
|
|
I/O operations are more efficient than Workers can be.
|
2017-09-01 17:03:41 +02:00
|
|
|
|
|
2019-01-09 00:18:19 +01:00
|
|
|
|
Unlike `child_process` or `cluster`, `worker_threads` can share memory. They do
|
|
|
|
|
so by transferring `ArrayBuffer` instances or sharing `SharedArrayBuffer`
|
|
|
|
|
instances.
|
2017-09-01 17:03:41 +02:00
|
|
|
|
|
|
|
|
|
```js
|
2018-06-01 15:13:43 +02:00
|
|
|
|
const {
|
|
|
|
|
Worker, isMainThread, parentPort, workerData
|
|
|
|
|
} = require('worker_threads');
|
2017-09-01 17:03:41 +02:00
|
|
|
|
|
|
|
|
|
if (isMainThread) {
|
2019-01-25 19:59:31 +01:00
|
|
|
|
module.exports = function parseJSAsync(script) {
|
2017-09-01 17:03:41 +02:00
|
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2019-01-09 00:18:19 +01:00
|
|
|
|
The above example spawns a Worker thread for each `parse()` call. In actual
|
|
|
|
|
practice, use a pool of Workers instead for these kinds of tasks. Otherwise, the
|
|
|
|
|
overhead of creating Workers would likely exceed their benefit.
|
2017-09-01 17:03:41 +02:00
|
|
|
|
|
2019-06-02 16:09:14 +02:00
|
|
|
|
When implementing a worker pool, use the [`AsyncResource`][] API to inform
|
|
|
|
|
diagnostic tools (e.g. in order to provide asynchronous stack traces) about the
|
2020-02-01 13:48:16 +01:00
|
|
|
|
correlation between tasks and their outcomes. See
|
|
|
|
|
["Using `AsyncResource` for a `Worker` thread pool"][async-resource-worker-pool]
|
|
|
|
|
in the `async_hooks` documentation for an example implementation.
|
2019-06-02 16:09:14 +02:00
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
## `worker.isMainThread`
|
2017-09-01 17:03:41 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2017-09-01 17:03:41 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
* {boolean}
|
|
|
|
|
|
|
|
|
|
Is `true` if this code is not running inside of a [`Worker`][] thread.
|
|
|
|
|
|
2019-02-14 22:10:03 +01:00
|
|
|
|
```js
|
|
|
|
|
const { Worker, isMainThread } = require('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'.
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
## `worker.moveMessagePortToContext(port, contextifiedSandbox)`
|
2017-09-10 01:43:55 +02:00
|
|
|
|
<!-- YAML
|
2019-03-27 22:43:03 +01:00
|
|
|
|
added: v11.13.0
|
2017-09-10 01:43:55 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
* `port` {MessagePort} The message port which will be transferred.
|
|
|
|
|
* `contextifiedSandbox` {Object} A [contextified][] object as returned by the
|
|
|
|
|
`vm.createContext()` method.
|
|
|
|
|
|
|
|
|
|
* Returns: {MessagePort}
|
|
|
|
|
|
|
|
|
|
Transfer a `MessagePort` to a different [`vm`][] Context. The original `port`
|
|
|
|
|
object will be rendered unusable, and the returned `MessagePort` instance will
|
|
|
|
|
take its place.
|
|
|
|
|
|
|
|
|
|
The returned `MessagePort` will be an object in the target context, and will
|
|
|
|
|
inherit from its global `Object` class. Objects passed to the
|
|
|
|
|
[`port.onmessage()`][] listener will also be created in the target context
|
|
|
|
|
and inherit from its global `Object` class.
|
|
|
|
|
|
|
|
|
|
However, the created `MessagePort` will no longer inherit from
|
|
|
|
|
[`EventEmitter`][], and only [`port.onmessage()`][] can be used to receive
|
|
|
|
|
events using it.
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
## `worker.parentPort`
|
2017-09-01 17:03:41 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2017-09-01 17:03:41 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
* {null|MessagePort}
|
|
|
|
|
|
|
|
|
|
If this thread was spawned as a [`Worker`][], this will be a [`MessagePort`][]
|
|
|
|
|
allowing communication with the parent thread. Messages sent using
|
|
|
|
|
`parentPort.postMessage()` will be available in the parent thread
|
|
|
|
|
using `worker.on('message')`, and messages sent from the parent thread
|
|
|
|
|
using `worker.postMessage()` will be available in this thread using
|
|
|
|
|
`parentPort.on('message')`.
|
|
|
|
|
|
2019-02-14 22:10:03 +01:00
|
|
|
|
```js
|
|
|
|
|
const { Worker, isMainThread, parentPort } = require('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);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
## `worker.receiveMessageOnPort(port)`
|
2019-04-18 00:56:57 +02:00
|
|
|
|
<!-- YAML
|
2019-05-21 13:49:35 +02:00
|
|
|
|
added: v12.3.0
|
2019-04-18 00:56:57 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
* `port` {MessagePort}
|
|
|
|
|
|
|
|
|
|
* Returns: {Object|undefined}
|
|
|
|
|
|
|
|
|
|
Receive a single message from a given `MessagePort`. If no message is available,
|
|
|
|
|
`undefined` is returned, otherwise an object with a single `message` property
|
|
|
|
|
that contains the message payload, corresponding to the oldest message in the
|
|
|
|
|
`MessagePort`’s queue.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
const { MessageChannel, receiveMessageOnPort } = require('worker_threads');
|
|
|
|
|
const { port1, port2 } = new MessageChannel();
|
|
|
|
|
port1.postMessage({ hello: 'world' });
|
|
|
|
|
|
|
|
|
|
console.log(receiveMessageOnPort(port2));
|
|
|
|
|
// Prints: { message: { hello: 'world' } }
|
|
|
|
|
console.log(receiveMessageOnPort(port2));
|
|
|
|
|
// Prints: undefined
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
When this function is used, no `'message'` event will be emitted and the
|
|
|
|
|
`onmessage` listener will not be invoked.
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
## `worker.resourceLimits`
|
2019-03-08 19:35:40 +01:00
|
|
|
|
<!-- YAML
|
2019-11-19 18:41:01 +01:00
|
|
|
|
added: v13.2.0
|
2019-03-08 19:35:40 +01:00
|
|
|
|
-->
|
|
|
|
|
|
2019-11-26 16:40:06 +01:00
|
|
|
|
* {Object}
|
2019-03-08 19:35:40 +01:00
|
|
|
|
* `maxYoungGenerationSizeMb` {number}
|
|
|
|
|
* `maxOldGenerationSizeMb` {number}
|
|
|
|
|
* `codeRangeSizeMb` {number}
|
|
|
|
|
|
|
|
|
|
Provides the set of JS engine resource constraints inside this Worker thread.
|
|
|
|
|
If the `resourceLimits` option was passed to the [`Worker`][] constructor,
|
|
|
|
|
this matches its values.
|
|
|
|
|
|
|
|
|
|
If this is used in the main thread, its value is an empty object.
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
## `worker.SHARE_ENV`
|
2019-02-22 20:11:19 +01:00
|
|
|
|
<!-- YAML
|
2019-04-10 00:55:02 +02:00
|
|
|
|
added: v11.14.0
|
2019-02-22 20:11:19 +01:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
* {symbol}
|
|
|
|
|
|
|
|
|
|
A special value that can be passed as the `env` option of the [`Worker`][]
|
|
|
|
|
constructor, to indicate that the current thread and the Worker thread should
|
|
|
|
|
share read and write access to the same set of environment variables.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
const { Worker, SHARE_ENV } = require('worker_threads');
|
|
|
|
|
new Worker('process.env.SET_IN_WORKER = "foo"', { eval: true, env: SHARE_ENV })
|
|
|
|
|
.on('exit', () => {
|
|
|
|
|
console.log(process.env.SET_IN_WORKER); // Prints 'foo'.
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
## `worker.threadId`
|
2017-09-01 17:03:41 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2017-09-01 17:03:41 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
* {integer}
|
|
|
|
|
|
|
|
|
|
An integer identifier for the current thread. On the corresponding worker object
|
|
|
|
|
(if there is any), it is available as [`worker.threadId`][].
|
2019-01-22 22:38:18 +01:00
|
|
|
|
This value is unique for each [`Worker`][] instance inside a single process.
|
2017-09-01 17:03:41 +02:00
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
## `worker.workerData`
|
2017-09-01 17:03:41 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2017-09-01 17:03:41 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
An arbitrary JavaScript value that contains a clone of the data passed
|
|
|
|
|
to this thread’s `Worker` constructor.
|
|
|
|
|
|
2019-02-14 22:10:03 +01:00
|
|
|
|
The data is cloned as if using [`postMessage()`][`port.postMessage()`],
|
|
|
|
|
according to the [HTML structured clone algorithm][].
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
const { Worker, isMainThread, workerData } = require('worker_threads');
|
|
|
|
|
|
|
|
|
|
if (isMainThread) {
|
|
|
|
|
const worker = new Worker(__filename, { workerData: 'Hello, world!' });
|
|
|
|
|
} else {
|
|
|
|
|
console.log(workerData); // Prints 'Hello, world!'.
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
## Class: `MessageChannel`
|
2017-09-05 22:38:32 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2017-09-05 22:38:32 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
Instances of the `worker.MessageChannel` class represent an asynchronous,
|
|
|
|
|
two-way communications channel.
|
|
|
|
|
The `MessageChannel` has no methods of its own. `new MessageChannel()`
|
|
|
|
|
yields an object with `port1` and `port2` properties, which refer to linked
|
|
|
|
|
[`MessagePort`][] instances.
|
|
|
|
|
|
|
|
|
|
```js
|
2018-06-01 15:13:43 +02:00
|
|
|
|
const { MessageChannel } = require('worker_threads');
|
2017-09-05 22:38:32 +02:00
|
|
|
|
|
|
|
|
|
const { port1, port2 } = new MessageChannel();
|
|
|
|
|
port1.on('message', (message) => console.log('received', message));
|
|
|
|
|
port2.postMessage({ foo: 'bar' });
|
2018-12-03 17:15:45 +01:00
|
|
|
|
// Prints: received { foo: 'bar' } from the `port1.on('message')` listener
|
2017-09-05 22:38:32 +02:00
|
|
|
|
```
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
## Class: `MessagePort`
|
2017-09-05 22:38:32 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2017-09-05 22:38:32 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
* Extends: {EventEmitter}
|
|
|
|
|
|
|
|
|
|
Instances of the `worker.MessagePort` class represent one end of an
|
|
|
|
|
asynchronous, two-way communications channel. It can be used to transfer
|
|
|
|
|
structured data, memory regions and other `MessagePort`s between different
|
|
|
|
|
[`Worker`][]s.
|
|
|
|
|
|
|
|
|
|
With the exception of `MessagePort`s being [`EventEmitter`][]s rather
|
2018-12-15 09:38:32 +01:00
|
|
|
|
than [`EventTarget`][]s, this implementation matches [browser `MessagePort`][]s.
|
2017-09-05 22:38:32 +02:00
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
### Event: `'close'`
|
2017-09-05 22:38:32 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2017-09-05 22:38:32 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
The `'close'` event is emitted once either side of the channel has been
|
|
|
|
|
disconnected.
|
|
|
|
|
|
2019-02-14 22:10:03 +01:00
|
|
|
|
```js
|
|
|
|
|
const { MessageChannel } = require('worker_threads');
|
|
|
|
|
const { port1, port2 } = new MessageChannel();
|
|
|
|
|
|
|
|
|
|
// Prints:
|
|
|
|
|
// foobar
|
|
|
|
|
// closed!
|
|
|
|
|
port2.on('message', (message) => console.log(message));
|
|
|
|
|
port2.on('close', () => console.log('closed!'));
|
|
|
|
|
|
|
|
|
|
port1.postMessage('foobar');
|
|
|
|
|
port1.close();
|
|
|
|
|
```
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
### Event: `'message'`
|
2017-09-05 22:38:32 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2017-09-05 22:38:32 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
* `value` {any} The transmitted value
|
|
|
|
|
|
|
|
|
|
The `'message'` event is emitted for any incoming message, containing the cloned
|
|
|
|
|
input of [`port.postMessage()`][].
|
|
|
|
|
|
|
|
|
|
Listeners on this event will receive a clone of the `value` parameter as passed
|
|
|
|
|
to `postMessage()` and no further arguments.
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
### `port.close()`
|
2017-09-05 22:38:32 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2017-09-05 22:38:32 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
Disables further sending of messages on either side of the connection.
|
2018-10-09 04:48:23 +02:00
|
|
|
|
This method can be called when no further communication will happen over this
|
|
|
|
|
`MessagePort`.
|
2017-09-05 22:38:32 +02:00
|
|
|
|
|
2019-02-14 22:10:03 +01:00
|
|
|
|
The [`'close'` event][] will be emitted on both `MessagePort` instances that
|
|
|
|
|
are part of the channel.
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
### `port.postMessage(value[, transferList])`
|
2017-09-05 22:38:32 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2017-09-05 22:38:32 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
* `value` {any}
|
|
|
|
|
* `transferList` {Object[]}
|
|
|
|
|
|
|
|
|
|
Sends a JavaScript value to the receiving side of this channel.
|
|
|
|
|
`value` will be transferred in a way which is compatible with
|
2019-02-14 22:10:03 +01:00
|
|
|
|
the [HTML structured clone algorithm][].
|
|
|
|
|
|
|
|
|
|
In particular, the significant differences to `JSON` are:
|
2019-09-06 07:42:22 +02:00
|
|
|
|
|
2019-09-13 06:22:29 +02:00
|
|
|
|
* `value` may contain circular references.
|
|
|
|
|
* `value` may contain instances of builtin JS types such as `RegExp`s,
|
2019-02-14 22:10:03 +01:00
|
|
|
|
`BigInt`s, `Map`s, `Set`s, etc.
|
2019-09-13 06:22:29 +02:00
|
|
|
|
* `value` may contain typed arrays, both using `ArrayBuffer`s
|
2019-02-14 22:10:03 +01:00
|
|
|
|
and `SharedArrayBuffer`s.
|
2019-09-13 06:22:29 +02:00
|
|
|
|
* `value` may contain [`WebAssembly.Module`][] instances.
|
|
|
|
|
* `value` may not contain native (C++-backed) objects other than `MessagePort`s.
|
2019-02-14 22:10:03 +01:00
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
const { MessageChannel } = require('worker_threads');
|
|
|
|
|
const { port1, port2 } = new MessageChannel();
|
|
|
|
|
|
|
|
|
|
port1.on('message', (message) => console.log(message));
|
|
|
|
|
|
|
|
|
|
const circularData = {};
|
|
|
|
|
circularData.foo = circularData;
|
|
|
|
|
// Prints: { foo: [Circular] }
|
|
|
|
|
port2.postMessage(circularData);
|
|
|
|
|
```
|
2017-09-05 22:38:32 +02:00
|
|
|
|
|
2017-10-07 23:39:02 +02:00
|
|
|
|
`transferList` may be a list of `ArrayBuffer` and `MessagePort` objects.
|
2017-09-05 22:38:32 +02:00
|
|
|
|
After transferring, they will not be usable on the sending side of the channel
|
2018-05-13 19:39:32 +02:00
|
|
|
|
anymore (even if they are not contained in `value`). Unlike with
|
|
|
|
|
[child processes][], transferring handles such as network sockets is currently
|
|
|
|
|
not supported.
|
|
|
|
|
|
|
|
|
|
If `value` contains [`SharedArrayBuffer`][] instances, those will be accessible
|
|
|
|
|
from either thread. They cannot be listed in `transferList`.
|
2017-09-05 22:38:32 +02:00
|
|
|
|
|
|
|
|
|
`value` may still contain `ArrayBuffer` instances that are not in
|
|
|
|
|
`transferList`; in that case, the underlying memory is copied rather than moved.
|
|
|
|
|
|
2019-02-14 22:10:03 +01:00
|
|
|
|
```js
|
|
|
|
|
const { MessageChannel } = require('worker_threads');
|
|
|
|
|
const { port1, port2 } = new MessageChannel();
|
|
|
|
|
|
|
|
|
|
port1.on('message', (message) => console.log(message));
|
|
|
|
|
|
|
|
|
|
const uint8Array = new Uint8Array([ 1, 2, 3, 4 ]);
|
|
|
|
|
// This posts a copy of `uint8Array`:
|
|
|
|
|
port2.postMessage(uint8Array);
|
|
|
|
|
// This does not copy data, but renders `uint8Array` unusable:
|
|
|
|
|
port2.postMessage(uint8Array, [ uint8Array.buffer ]);
|
|
|
|
|
|
|
|
|
|
// The memory for the `sharedUint8Array` will be accessible from both the
|
|
|
|
|
// original and the copy received by `.on('message')`:
|
|
|
|
|
const sharedUint8Array = new Uint8Array(new SharedArrayBuffer(4));
|
|
|
|
|
port2.postMessage(sharedUint8Array);
|
|
|
|
|
|
|
|
|
|
// This transfers a freshly created message port to the receiver.
|
|
|
|
|
// This can be used, for example, to create communication channels between
|
|
|
|
|
// multiple `Worker` threads that are children of the same parent thread.
|
|
|
|
|
const otherChannel = new MessageChannel();
|
|
|
|
|
port2.postMessage({ port: otherChannel.port1 }, [ otherChannel.port1 ]);
|
|
|
|
|
```
|
|
|
|
|
|
2017-09-05 22:38:32 +02:00
|
|
|
|
Because the object cloning uses the structured clone algorithm,
|
|
|
|
|
non-enumerable properties, property accessors, and object prototypes are
|
|
|
|
|
not preserved. In particular, [`Buffer`][] objects will be read as
|
|
|
|
|
plain [`Uint8Array`][]s on the receiving side.
|
|
|
|
|
|
|
|
|
|
The message object will be cloned immediately, and can be modified after
|
|
|
|
|
posting without having side effects.
|
|
|
|
|
|
2018-05-13 19:39:32 +02:00
|
|
|
|
For more information on the serialization and deserialization mechanisms
|
|
|
|
|
behind this API, see the [serialization API of the `v8` module][v8.serdes].
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
### `port.ref()`
|
2017-09-05 22:38:32 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2017-09-05 22:38:32 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
Opposite of `unref()`. Calling `ref()` on a previously `unref()`ed port will
|
|
|
|
|
*not* let the program exit if it's the only active handle left (the default
|
|
|
|
|
behavior). If the port is `ref()`ed, calling `ref()` again will have no effect.
|
|
|
|
|
|
|
|
|
|
If listeners are attached or removed using `.on('message')`, the port will
|
|
|
|
|
be `ref()`ed and `unref()`ed automatically depending on whether
|
|
|
|
|
listeners for the event exist.
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
### `port.start()`
|
2017-09-05 22:38:32 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2017-09-05 22:38:32 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
Starts receiving messages on this `MessagePort`. When using this port
|
|
|
|
|
as an event emitter, this will be called automatically once `'message'`
|
|
|
|
|
listeners are attached.
|
|
|
|
|
|
2019-02-14 22:10:03 +01:00
|
|
|
|
This method exists for parity with the Web `MessagePort` API. In Node.js,
|
|
|
|
|
it is only useful for ignoring messages when no event listener is present.
|
2019-03-10 12:12:59 +01:00
|
|
|
|
Node.js also diverges in its handling of `.onmessage`. Setting it will
|
|
|
|
|
automatically call `.start()`, but unsetting it will let messages queue up
|
|
|
|
|
until a new handler is set or the port is discarded.
|
2019-02-14 22:10:03 +01:00
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
### `port.unref()`
|
2017-09-05 22:38:32 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2017-09-05 22:38:32 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
Calling `unref()` on a port will allow the thread to exit if this is the only
|
|
|
|
|
active handle in the event system. If the port is already `unref()`ed calling
|
|
|
|
|
`unref()` again will have no effect.
|
|
|
|
|
|
|
|
|
|
If listeners are attached or removed using `.on('message')`, the port will
|
|
|
|
|
be `ref()`ed and `unref()`ed automatically depending on whether
|
|
|
|
|
listeners for the event exist.
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
## Class: `Worker`
|
2017-09-01 17:03:41 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2017-09-01 17:03:41 +02:00
|
|
|
|
-->
|
|
|
|
|
|
2018-12-05 13:31:01 +01:00
|
|
|
|
* Extends: {EventEmitter}
|
|
|
|
|
|
2017-09-01 17:03:41 +02:00
|
|
|
|
The `Worker` class represents an independent JavaScript execution thread.
|
|
|
|
|
Most Node.js APIs are available inside of it.
|
|
|
|
|
|
|
|
|
|
Notable differences inside a Worker environment are:
|
|
|
|
|
|
2019-09-13 06:22:29 +02:00
|
|
|
|
* The [`process.stdin`][], [`process.stdout`][] and [`process.stderr`][]
|
2018-05-13 23:25:14 +02:00
|
|
|
|
may be redirected by the parent thread.
|
2019-09-13 06:22:29 +02:00
|
|
|
|
* The [`require('worker_threads').isMainThread`][] property is set to `false`.
|
|
|
|
|
* The [`require('worker_threads').parentPort`][] message port is available.
|
|
|
|
|
* [`process.exit()`][] does not stop the whole program, just the single thread,
|
2017-09-01 17:03:41 +02:00
|
|
|
|
and [`process.abort()`][] is not available.
|
2019-09-13 06:22:29 +02:00
|
|
|
|
* [`process.chdir()`][] and `process` methods that set group or user ids
|
2017-09-01 17:03:41 +02:00
|
|
|
|
are not available.
|
2019-09-13 06:22:29 +02:00
|
|
|
|
* [`process.env`][] is a copy of the parent thread's environment variables,
|
2019-02-22 20:11:19 +01:00
|
|
|
|
unless otherwise specified. Changes to one copy will not be visible in other
|
|
|
|
|
threads, and will not be visible to native add-ons (unless
|
|
|
|
|
[`worker.SHARE_ENV`][] has been passed as the `env` option to the
|
|
|
|
|
[`Worker`][] constructor).
|
2019-09-13 06:22:29 +02:00
|
|
|
|
* [`process.title`][] cannot be modified.
|
|
|
|
|
* Signals will not be delivered through [`process.on('...')`][Signals events].
|
|
|
|
|
* Execution may stop at any point as a result of [`worker.terminate()`][]
|
2017-09-01 17:03:41 +02:00
|
|
|
|
being invoked.
|
2019-09-13 06:22:29 +02:00
|
|
|
|
* IPC channels from parent processes are not accessible.
|
|
|
|
|
* The [`trace_events`][] module is not supported.
|
|
|
|
|
* Native add-ons can only be loaded from multiple threads if they fulfill
|
2019-02-17 23:45:14 +01:00
|
|
|
|
[certain conditions][Addons worker support].
|
2017-09-01 17:03:41 +02:00
|
|
|
|
|
|
|
|
|
Creating `Worker` instances inside of other `Worker`s is possible.
|
|
|
|
|
|
|
|
|
|
Like [Web Workers][] and the [`cluster` module][], two-way communication can be
|
|
|
|
|
achieved through inter-thread message passing. Internally, a `Worker` has a
|
|
|
|
|
built-in pair of [`MessagePort`][]s that are already associated with each other
|
|
|
|
|
when the `Worker` is created. While the `MessagePort` object on the parent side
|
|
|
|
|
is not directly exposed, its functionalities are exposed through
|
|
|
|
|
[`worker.postMessage()`][] and the [`worker.on('message')`][] event
|
|
|
|
|
on the `Worker` object for the parent thread.
|
|
|
|
|
|
|
|
|
|
To create custom messaging channels (which is encouraged over using the default
|
|
|
|
|
global channel because it facilitates separation of concerns), users can create
|
|
|
|
|
a `MessageChannel` object on either thread and pass one of the
|
|
|
|
|
`MessagePort`s on that `MessageChannel` to the other thread through a
|
|
|
|
|
pre-existing channel, such as the global one.
|
|
|
|
|
|
|
|
|
|
See [`port.postMessage()`][] for more information on how messages are passed,
|
|
|
|
|
and what kind of JavaScript values can be successfully transported through
|
|
|
|
|
the thread barrier.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
const assert = require('assert');
|
2018-06-01 15:13:43 +02:00
|
|
|
|
const {
|
2018-07-08 06:32:23 +02:00
|
|
|
|
Worker, MessageChannel, MessagePort, isMainThread, parentPort
|
2018-06-01 15:13:43 +02:00
|
|
|
|
} = require('worker_threads');
|
2017-09-01 17:03:41 +02:00
|
|
|
|
if (isMainThread) {
|
|
|
|
|
const worker = new Worker(__filename);
|
|
|
|
|
const subChannel = new MessageChannel();
|
|
|
|
|
worker.postMessage({ hereIsYourPort: subChannel.port1 }, [subChannel.port1]);
|
|
|
|
|
subChannel.port2.on('message', (value) => {
|
|
|
|
|
console.log('received:', value);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
2018-07-08 06:32:23 +02:00
|
|
|
|
parentPort.once('message', (value) => {
|
2017-09-01 17:03:41 +02:00
|
|
|
|
assert(value.hereIsYourPort instanceof MessagePort);
|
|
|
|
|
value.hereIsYourPort.postMessage('the worker is sending this');
|
|
|
|
|
value.hereIsYourPort.close();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
### `new Worker(filename[, options])`
|
2019-03-08 19:35:40 +01:00
|
|
|
|
<!-- YAML
|
|
|
|
|
added: v10.5.0
|
|
|
|
|
changes:
|
2019-11-19 18:41:01 +01:00
|
|
|
|
- version: v13.2.0
|
2019-03-08 19:35:40 +01:00
|
|
|
|
pr-url: https://github.com/nodejs/node/pull/26628
|
|
|
|
|
description: The `resourceLimits` option was introduced.
|
2019-12-13 17:02:36 +01:00
|
|
|
|
- version: v13.4.0
|
2019-11-20 17:55:36 +01:00
|
|
|
|
pr-url: https://github.com/nodejs/node/pull/30559
|
|
|
|
|
description: The `argv` option was introduced.
|
2019-03-08 19:35:40 +01:00
|
|
|
|
-->
|
2017-09-01 17:03:41 +02:00
|
|
|
|
|
2018-06-26 17:31:36 +02:00
|
|
|
|
* `filename` {string} The path to the Worker’s main script. Must be
|
|
|
|
|
either an absolute path or a relative path (i.e. relative to the
|
|
|
|
|
current working directory) starting with `./` or `../`.
|
2018-12-15 09:38:32 +01:00
|
|
|
|
If `options.eval` is `true`, this is a string containing JavaScript code
|
|
|
|
|
rather than a path.
|
2017-09-01 17:03:41 +02:00
|
|
|
|
* `options` {Object}
|
2019-11-20 17:55:36 +01:00
|
|
|
|
* `argv` {any[]} List of arguments which would be stringified and appended to
|
|
|
|
|
`process.argv` in the worker. This is mostly similar to the `workerData`
|
|
|
|
|
but the values will be available on the global `process.argv` as if they
|
|
|
|
|
were passed as CLI options to the script.
|
2019-02-22 20:11:19 +01:00
|
|
|
|
* `env` {Object} If set, specifies the initial value of `process.env` inside
|
|
|
|
|
the Worker thread. As a special value, [`worker.SHARE_ENV`][] may be used
|
|
|
|
|
to specify that the parent thread and the child thread should share their
|
|
|
|
|
environment variables; in that case, changes to one thread’s `process.env`
|
|
|
|
|
object will affect the other thread as well. **Default:** `process.env`.
|
2018-12-15 09:38:32 +01:00
|
|
|
|
* `eval` {boolean} If `true`, interpret the first argument to the constructor
|
2017-09-01 17:03:41 +02:00
|
|
|
|
as a script that is executed once the worker is online.
|
2019-02-22 20:11:19 +01:00
|
|
|
|
* `execArgv` {string[]} List of node CLI options passed to the worker.
|
|
|
|
|
V8 options (such as `--max-old-space-size`) and options that affect the
|
|
|
|
|
process (such as `--title`) are not supported. If set, this will be provided
|
|
|
|
|
as [`process.execArgv`][] inside the worker. By default, options will be
|
|
|
|
|
inherited from the parent thread.
|
2019-01-04 19:02:25 +01:00
|
|
|
|
* `stdin` {boolean} If this is set to `true`, then `worker.stdin` will
|
2018-05-13 23:25:14 +02:00
|
|
|
|
provide a writable stream whose contents will appear as `process.stdin`
|
|
|
|
|
inside the Worker. By default, no data is provided.
|
2019-01-04 19:02:25 +01:00
|
|
|
|
* `stdout` {boolean} If this is set to `true`, then `worker.stdout` will
|
2018-05-13 23:25:14 +02:00
|
|
|
|
not automatically be piped through to `process.stdout` in the parent.
|
2019-01-04 19:02:25 +01:00
|
|
|
|
* `stderr` {boolean} If this is set to `true`, then `worker.stderr` will
|
2018-05-13 23:25:14 +02:00
|
|
|
|
not automatically be piped through to `process.stderr` in the parent.
|
2019-02-22 20:11:19 +01:00
|
|
|
|
* `workerData` {any} Any JavaScript value that will be cloned and made
|
|
|
|
|
available as [`require('worker_threads').workerData`][]. The cloning will
|
|
|
|
|
occur as described in the [HTML structured clone algorithm][], and an error
|
|
|
|
|
will be thrown if the object cannot be cloned (e.g. because it contains
|
|
|
|
|
`function`s).
|
2019-03-08 19:35:40 +01:00
|
|
|
|
* `resourceLimits` {Object} An optional set of resource limits for the new
|
|
|
|
|
JS engine instance. Reaching these limits will lead to termination of the
|
|
|
|
|
`Worker` instance. These limits only affect the JS engine, and no external
|
|
|
|
|
data, including no `ArrayBuffer`s. Even if these limits are set, the process
|
|
|
|
|
may still abort if it encounters a global out-of-memory situation.
|
|
|
|
|
* `maxOldGenerationSizeMb` {number} The maximum size of the main heap in MB.
|
|
|
|
|
* `maxYoungGenerationSizeMb` {number} The maximum size of a heap space for
|
|
|
|
|
recently created objects.
|
|
|
|
|
* `codeRangeSizeMb` {number} The size of a pre-allocated memory range
|
|
|
|
|
used for generated code.
|
2017-09-01 17:03:41 +02:00
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
### Event: `'error'`
|
2017-09-01 17:03:41 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2017-09-01 17:03:41 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
* `err` {Error}
|
|
|
|
|
|
|
|
|
|
The `'error'` event is emitted if the worker thread throws an uncaught
|
|
|
|
|
exception. In that case, the worker will be terminated.
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
### Event: `'exit'`
|
2017-09-01 17:03:41 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2017-09-01 17:03:41 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
* `exitCode` {integer}
|
|
|
|
|
|
|
|
|
|
The `'exit'` event is emitted once the worker has stopped. If the worker
|
|
|
|
|
exited by calling [`process.exit()`][], the `exitCode` parameter will be the
|
|
|
|
|
passed exit code. If the worker was terminated, the `exitCode` parameter will
|
|
|
|
|
be `1`.
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
### Event: `'message'`
|
2017-09-01 17:03:41 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2017-09-01 17:03:41 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
* `value` {any} The transmitted value
|
|
|
|
|
|
|
|
|
|
The `'message'` event is emitted when the worker thread has invoked
|
2019-01-03 23:58:37 +01:00
|
|
|
|
[`require('worker_threads').parentPort.postMessage()`][].
|
|
|
|
|
See the [`port.on('message')`][] event for more details.
|
2017-09-01 17:03:41 +02:00
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
### Event: `'online'`
|
2017-09-01 17:03:41 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2017-09-01 17:03:41 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
The `'online'` event is emitted when the worker thread has started executing
|
|
|
|
|
JavaScript code.
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
### `worker.postMessage(value[, transferList])`
|
2017-09-01 17:03:41 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2017-09-01 17:03:41 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
* `value` {any}
|
|
|
|
|
* `transferList` {Object[]}
|
|
|
|
|
|
|
|
|
|
Send a message to the worker that will be received via
|
2018-06-23 13:40:10 +02:00
|
|
|
|
[`require('worker_threads').parentPort.on('message')`][].
|
2018-06-01 15:13:43 +02:00
|
|
|
|
See [`port.postMessage()`][] for more details.
|
2017-09-01 17:03:41 +02:00
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
### `worker.ref()`
|
2017-09-01 17:03:41 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2017-09-01 17:03:41 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
Opposite of `unref()`, calling `ref()` on a previously `unref()`ed worker will
|
|
|
|
|
*not* let the program exit if it's the only active handle left (the default
|
|
|
|
|
behavior). If the worker is `ref()`ed, calling `ref()` again will have
|
|
|
|
|
no effect.
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
### `worker.resourceLimits`
|
2019-03-08 19:35:40 +01:00
|
|
|
|
<!-- YAML
|
2019-11-19 18:41:01 +01:00
|
|
|
|
added: v13.2.0
|
2019-03-08 19:35:40 +01:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
* {Object}
|
|
|
|
|
* `maxYoungGenerationSizeMb` {number}
|
|
|
|
|
* `maxOldGenerationSizeMb` {number}
|
|
|
|
|
* `codeRangeSizeMb` {number}
|
|
|
|
|
|
|
|
|
|
Provides the set of JS engine resource constraints for this Worker thread.
|
|
|
|
|
If the `resourceLimits` option was passed to the [`Worker`][] constructor,
|
|
|
|
|
this matches its values.
|
|
|
|
|
|
|
|
|
|
If the worker has stopped, the return value is an empty object.
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
### `worker.stderr`
|
2018-05-13 23:25:14 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2018-05-13 23:25:14 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
* {stream.Readable}
|
|
|
|
|
|
|
|
|
|
This is a readable stream which contains data written to [`process.stderr`][]
|
|
|
|
|
inside the worker thread. If `stderr: true` was not passed to the
|
|
|
|
|
[`Worker`][] constructor, then data will be piped to the parent thread's
|
|
|
|
|
[`process.stderr`][] stream.
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
### `worker.stdin`
|
2018-05-13 23:25:14 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2018-05-13 23:25:14 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
* {null|stream.Writable}
|
|
|
|
|
|
|
|
|
|
If `stdin: true` was passed to the [`Worker`][] constructor, this is a
|
|
|
|
|
writable stream. The data written to this stream will be made available in
|
|
|
|
|
the worker thread as [`process.stdin`][].
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
### `worker.stdout`
|
2018-05-13 23:25:14 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2018-05-13 23:25:14 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
* {stream.Readable}
|
|
|
|
|
|
|
|
|
|
This is a readable stream which contains data written to [`process.stdout`][]
|
|
|
|
|
inside the worker thread. If `stdout: true` was not passed to the
|
|
|
|
|
[`Worker`][] constructor, then data will be piped to the parent thread's
|
|
|
|
|
[`process.stdout`][] stream.
|
|
|
|
|
|
2020-01-29 17:41:26 +01:00
|
|
|
|
### `worker.takeHeapSnapshot()`
|
|
|
|
|
<!-- YAML
|
|
|
|
|
added: REPLACEME
|
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
* Returns: {Promise} A promise for a Readable Stream containing
|
|
|
|
|
a V8 heap snapshot
|
|
|
|
|
|
|
|
|
|
Returns a readable stream for a V8 snapshot of the current state of the Worker.
|
|
|
|
|
See [`v8.getHeapSnapshot()`][] for more details.
|
|
|
|
|
|
|
|
|
|
If the Worker thread is no longer running, which may occur before the
|
|
|
|
|
[`'exit'` event][] is emitted, the returned `Promise` will be rejected
|
|
|
|
|
immediately with an [`ERR_WORKER_NOT_RUNNING`][] error.
|
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
### `worker.terminate()`
|
2017-09-01 17:03:41 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
worker: refactor `worker.terminate()`
At the collaborator summit in Berlin, the behaviour of
`worker.terminate()` was discussed.
In particular, switching from a callback-based to a Promise-based API
was suggested. While investigating that possibility later, it was
discovered that `.terminate()` was unintentionally synchronous up
until now (including calling its callback synchronously).
Also, the topic of its stability has been brought up. I have performed
two manual reviews of the native codebase for compatibility with
`.terminate()`, and performed some manual fuzz testing with the test
suite. At this point, bugs with `.terminate()` should, in my opinion,
be treated like bugs in other Node.js features.
(It is possible to make Node.js crash with `.terminate()` by messing
with internals and/or built-in prototype objects, but that is already
the case without `.terminate()` as well.)
This commit:
- Makes `.terminate()` an asynchronous operation.
- Makes `.terminate()` return a `Promise`.
- Runtime-deprecates passing a callback.
- Removes a warning about its stability from the documentation.
- Eliminates an unnecessary extra function from the C++ code.
A possible alternative to returning a `Promise` would be to keep the
method synchronous and just drop the callback. Generally, providing
an asynchronous API does provide us with a bit more flexibility.
Refs: https://github.com/nodejs/summit/issues/141
PR-URL: https://github.com/nodejs/node/pull/28021
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2019-06-02 15:09:57 +02:00
|
|
|
|
changes:
|
2019-06-17 21:31:37 +02:00
|
|
|
|
- version: v12.5.0
|
worker: refactor `worker.terminate()`
At the collaborator summit in Berlin, the behaviour of
`worker.terminate()` was discussed.
In particular, switching from a callback-based to a Promise-based API
was suggested. While investigating that possibility later, it was
discovered that `.terminate()` was unintentionally synchronous up
until now (including calling its callback synchronously).
Also, the topic of its stability has been brought up. I have performed
two manual reviews of the native codebase for compatibility with
`.terminate()`, and performed some manual fuzz testing with the test
suite. At this point, bugs with `.terminate()` should, in my opinion,
be treated like bugs in other Node.js features.
(It is possible to make Node.js crash with `.terminate()` by messing
with internals and/or built-in prototype objects, but that is already
the case without `.terminate()` as well.)
This commit:
- Makes `.terminate()` an asynchronous operation.
- Makes `.terminate()` return a `Promise`.
- Runtime-deprecates passing a callback.
- Removes a warning about its stability from the documentation.
- Eliminates an unnecessary extra function from the C++ code.
A possible alternative to returning a `Promise` would be to keep the
method synchronous and just drop the callback. Generally, providing
an asynchronous API does provide us with a bit more flexibility.
Refs: https://github.com/nodejs/summit/issues/141
PR-URL: https://github.com/nodejs/node/pull/28021
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2019-06-02 15:09:57 +02:00
|
|
|
|
pr-url: https://github.com/nodejs/node/pull/28021
|
|
|
|
|
description: This function now returns a Promise.
|
|
|
|
|
Passing a callback is deprecated, and was useless up to this
|
|
|
|
|
version, as the Worker was actually terminated synchronously.
|
|
|
|
|
Terminating is now a fully asynchronous operation.
|
2017-09-01 17:03:41 +02:00
|
|
|
|
-->
|
|
|
|
|
|
worker: refactor `worker.terminate()`
At the collaborator summit in Berlin, the behaviour of
`worker.terminate()` was discussed.
In particular, switching from a callback-based to a Promise-based API
was suggested. While investigating that possibility later, it was
discovered that `.terminate()` was unintentionally synchronous up
until now (including calling its callback synchronously).
Also, the topic of its stability has been brought up. I have performed
two manual reviews of the native codebase for compatibility with
`.terminate()`, and performed some manual fuzz testing with the test
suite. At this point, bugs with `.terminate()` should, in my opinion,
be treated like bugs in other Node.js features.
(It is possible to make Node.js crash with `.terminate()` by messing
with internals and/or built-in prototype objects, but that is already
the case without `.terminate()` as well.)
This commit:
- Makes `.terminate()` an asynchronous operation.
- Makes `.terminate()` return a `Promise`.
- Runtime-deprecates passing a callback.
- Removes a warning about its stability from the documentation.
- Eliminates an unnecessary extra function from the C++ code.
A possible alternative to returning a `Promise` would be to keep the
method synchronous and just drop the callback. Generally, providing
an asynchronous API does provide us with a bit more flexibility.
Refs: https://github.com/nodejs/summit/issues/141
PR-URL: https://github.com/nodejs/node/pull/28021
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2019-06-02 15:09:57 +02:00
|
|
|
|
* Returns: {Promise}
|
2017-09-01 17:03:41 +02:00
|
|
|
|
|
|
|
|
|
Stop all JavaScript execution in the worker thread as soon as possible.
|
worker: refactor `worker.terminate()`
At the collaborator summit in Berlin, the behaviour of
`worker.terminate()` was discussed.
In particular, switching from a callback-based to a Promise-based API
was suggested. While investigating that possibility later, it was
discovered that `.terminate()` was unintentionally synchronous up
until now (including calling its callback synchronously).
Also, the topic of its stability has been brought up. I have performed
two manual reviews of the native codebase for compatibility with
`.terminate()`, and performed some manual fuzz testing with the test
suite. At this point, bugs with `.terminate()` should, in my opinion,
be treated like bugs in other Node.js features.
(It is possible to make Node.js crash with `.terminate()` by messing
with internals and/or built-in prototype objects, but that is already
the case without `.terminate()` as well.)
This commit:
- Makes `.terminate()` an asynchronous operation.
- Makes `.terminate()` return a `Promise`.
- Runtime-deprecates passing a callback.
- Removes a warning about its stability from the documentation.
- Eliminates an unnecessary extra function from the C++ code.
A possible alternative to returning a `Promise` would be to keep the
method synchronous and just drop the callback. Generally, providing
an asynchronous API does provide us with a bit more flexibility.
Refs: https://github.com/nodejs/summit/issues/141
PR-URL: https://github.com/nodejs/node/pull/28021
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2019-06-02 15:09:57 +02:00
|
|
|
|
Returns a Promise for the exit code that is fulfilled when the
|
|
|
|
|
[`'exit'` event][] is emitted.
|
2017-09-01 17:03:41 +02:00
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
### `worker.threadId`
|
2017-09-01 17:03:41 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2017-09-01 17:03:41 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
* {integer}
|
|
|
|
|
|
|
|
|
|
An integer identifier for the referenced thread. Inside the worker thread,
|
2018-06-01 15:13:43 +02:00
|
|
|
|
it is available as [`require('worker_threads').threadId`][].
|
2019-01-22 22:38:18 +01:00
|
|
|
|
This value is unique for each `Worker` instance inside a single process.
|
2017-09-01 17:03:41 +02:00
|
|
|
|
|
2019-12-25 00:58:43 +01:00
|
|
|
|
### `worker.unref()`
|
2017-09-01 17:03:41 +02:00
|
|
|
|
<!-- YAML
|
2018-06-19 09:35:50 +02:00
|
|
|
|
added: v10.5.0
|
2017-09-01 17:03:41 +02:00
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
Calling `unref()` on a worker will allow the thread to exit if this is the only
|
|
|
|
|
active handle in the event system. If the worker is already `unref()`ed calling
|
|
|
|
|
`unref()` again will have no effect.
|
|
|
|
|
|
2019-02-14 22:10:03 +01:00
|
|
|
|
[`'close'` event]: #worker_threads_event_close
|
worker: refactor `worker.terminate()`
At the collaborator summit in Berlin, the behaviour of
`worker.terminate()` was discussed.
In particular, switching from a callback-based to a Promise-based API
was suggested. While investigating that possibility later, it was
discovered that `.terminate()` was unintentionally synchronous up
until now (including calling its callback synchronously).
Also, the topic of its stability has been brought up. I have performed
two manual reviews of the native codebase for compatibility with
`.terminate()`, and performed some manual fuzz testing with the test
suite. At this point, bugs with `.terminate()` should, in my opinion,
be treated like bugs in other Node.js features.
(It is possible to make Node.js crash with `.terminate()` by messing
with internals and/or built-in prototype objects, but that is already
the case without `.terminate()` as well.)
This commit:
- Makes `.terminate()` an asynchronous operation.
- Makes `.terminate()` return a `Promise`.
- Runtime-deprecates passing a callback.
- Removes a warning about its stability from the documentation.
- Eliminates an unnecessary extra function from the C++ code.
A possible alternative to returning a `Promise` would be to keep the
method synchronous and just drop the callback. Generally, providing
an asynchronous API does provide us with a bit more flexibility.
Refs: https://github.com/nodejs/summit/issues/141
PR-URL: https://github.com/nodejs/node/pull/28021
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2019-06-02 15:09:57 +02:00
|
|
|
|
[`'exit'` event]: #worker_threads_event_exit
|
2019-06-02 16:09:14 +02:00
|
|
|
|
[`AsyncResource`]: async_hooks.html#async_hooks_class_asyncresource
|
2017-09-05 22:38:32 +02:00
|
|
|
|
[`Buffer`]: buffer.html
|
2020-01-29 17:41:26 +01:00
|
|
|
|
[`ERR_WORKER_NOT_RUNNING`]: errors.html#ERR_WORKER_NOT_RUNNING
|
2017-09-05 22:38:32 +02:00
|
|
|
|
[`EventEmitter`]: events.html
|
2018-12-15 09:38:32 +01:00
|
|
|
|
[`EventTarget`]: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget
|
2018-06-01 15:13:43 +02:00
|
|
|
|
[`MessagePort`]: #worker_threads_class_messageport
|
2018-11-27 20:49:21 +01:00
|
|
|
|
[`SharedArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer
|
|
|
|
|
[`Uint8Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array
|
2019-02-14 22:10:03 +01:00
|
|
|
|
[`WebAssembly.Module`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module
|
2018-06-01 15:13:43 +02:00
|
|
|
|
[`Worker`]: #worker_threads_class_worker
|
2018-11-27 20:49:21 +01:00
|
|
|
|
[`cluster` module]: cluster.html
|
2018-06-01 15:13:43 +02:00
|
|
|
|
[`port.on('message')`]: #worker_threads_event_message
|
2017-09-10 01:43:55 +02:00
|
|
|
|
[`port.onmessage()`]: https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/onmessage
|
2018-11-27 20:49:21 +01:00
|
|
|
|
[`port.postMessage()`]: #worker_threads_port_postmessage_value_transferlist
|
2017-09-01 17:03:41 +02:00
|
|
|
|
[`process.abort()`]: process.html#process_process_abort
|
|
|
|
|
[`process.chdir()`]: process.html#process_process_chdir_directory
|
|
|
|
|
[`process.env`]: process.html#process_process_env
|
2019-02-22 21:01:22 +01:00
|
|
|
|
[`process.execArgv`]: process.html#process_process_execargv
|
2018-11-27 20:49:21 +01:00
|
|
|
|
[`process.exit()`]: process.html#process_process_exit_code
|
2017-09-01 17:03:41 +02:00
|
|
|
|
[`process.stderr`]: process.html#process_process_stderr
|
2018-11-27 20:49:21 +01:00
|
|
|
|
[`process.stdin`]: process.html#process_process_stdin
|
2017-09-01 17:03:41 +02:00
|
|
|
|
[`process.stdout`]: process.html#process_process_stdout
|
|
|
|
|
[`process.title`]: process.html#process_process_title
|
2018-06-01 15:13:43 +02:00
|
|
|
|
[`require('worker_threads').isMainThread`]: #worker_threads_worker_ismainthread
|
2018-11-27 20:49:21 +01:00
|
|
|
|
[`require('worker_threads').parentPort.on('message')`]: #worker_threads_event_message
|
2018-06-20 23:35:30 +02:00
|
|
|
|
[`require('worker_threads').parentPort`]: #worker_threads_worker_parentport
|
2019-01-03 23:58:37 +01:00
|
|
|
|
[`require('worker_threads').parentPort.postMessage()`]: #worker_threads_worker_postmessage_value_transferlist
|
2018-06-01 15:13:43 +02:00
|
|
|
|
[`require('worker_threads').threadId`]: #worker_threads_worker_threadid
|
2018-11-27 20:49:21 +01:00
|
|
|
|
[`require('worker_threads').workerData`]: #worker_threads_worker_workerdata
|
2018-10-20 11:51:29 +02:00
|
|
|
|
[`trace_events`]: tracing.html
|
2020-01-29 17:41:26 +01:00
|
|
|
|
[`v8.getHeapSnapshot()`]: v8.html#v8_v8_getheapsnapshot
|
2017-09-10 01:43:55 +02:00
|
|
|
|
[`vm`]: vm.html
|
2018-11-27 20:49:21 +01:00
|
|
|
|
[`worker.on('message')`]: #worker_threads_event_message_1
|
|
|
|
|
[`worker.postMessage()`]: #worker_threads_worker_postmessage_value_transferlist
|
2019-02-22 20:11:19 +01:00
|
|
|
|
[`worker.SHARE_ENV`]: #worker_threads_worker_share_env
|
worker: refactor `worker.terminate()`
At the collaborator summit in Berlin, the behaviour of
`worker.terminate()` was discussed.
In particular, switching from a callback-based to a Promise-based API
was suggested. While investigating that possibility later, it was
discovered that `.terminate()` was unintentionally synchronous up
until now (including calling its callback synchronously).
Also, the topic of its stability has been brought up. I have performed
two manual reviews of the native codebase for compatibility with
`.terminate()`, and performed some manual fuzz testing with the test
suite. At this point, bugs with `.terminate()` should, in my opinion,
be treated like bugs in other Node.js features.
(It is possible to make Node.js crash with `.terminate()` by messing
with internals and/or built-in prototype objects, but that is already
the case without `.terminate()` as well.)
This commit:
- Makes `.terminate()` an asynchronous operation.
- Makes `.terminate()` return a `Promise`.
- Runtime-deprecates passing a callback.
- Removes a warning about its stability from the documentation.
- Eliminates an unnecessary extra function from the C++ code.
A possible alternative to returning a `Promise` would be to keep the
method synchronous and just drop the callback. Generally, providing
an asynchronous API does provide us with a bit more flexibility.
Refs: https://github.com/nodejs/summit/issues/141
PR-URL: https://github.com/nodejs/node/pull/28021
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2019-06-02 15:09:57 +02:00
|
|
|
|
[`worker.terminate()`]: #worker_threads_worker_terminate
|
2018-11-27 20:49:21 +01:00
|
|
|
|
[`worker.threadId`]: #worker_threads_worker_threadid_1
|
2019-02-17 23:45:14 +01:00
|
|
|
|
[Addons worker support]: addons.html#addons_worker_support
|
2020-02-01 13:48:16 +01:00
|
|
|
|
[async-resource-worker-pool]: async_hooks.html#async-resource-worker-pool
|
2017-09-05 22:38:32 +02:00
|
|
|
|
[HTML structured clone algorithm]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
|
2018-11-27 20:49:21 +01:00
|
|
|
|
[Signals events]: process.html#process_signal_events
|
2017-09-01 17:03:41 +02:00
|
|
|
|
[Web Workers]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
|
2018-11-27 20:49:21 +01:00
|
|
|
|
[browser `MessagePort`]: https://developer.mozilla.org/en-US/docs/Web/API/MessagePort
|
|
|
|
|
[child processes]: child_process.html
|
2017-09-10 01:43:55 +02:00
|
|
|
|
[contextified]: vm.html#vm_what_does_it_mean_to_contextify_an_object
|
2018-11-27 20:49:21 +01:00
|
|
|
|
[v8.serdes]: v8.html#v8_serialization_api
|