Skip to content

Commit

Permalink
doc: improve worker_threads documentation
Browse files Browse the repository at this point in the history
This adds a few examples and clarifications.

PR-URL: #26110
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Anto Aravinth <anto.aravinth.cse@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com>
  • Loading branch information
addaleax authored and rvagg committed Feb 28, 2019
1 parent d3525d7 commit a18b847
Showing 1 changed file with 112 additions and 5 deletions.
117 changes: 112 additions & 5 deletions doc/api/worker_threads.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

> Stability: 1 - Experimental
The `worker_threads` module enables the use of threads with message channels
between them. To access it:
The `worker_threads` module enables the use of threads that execute JS code
in parallel. To access it:

```js
const worker = require('worker_threads');
Expand Down Expand Up @@ -58,6 +58,18 @@ added: v10.5.0

Is `true` if this code is not running inside of a [`Worker`][] thread.

```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'.
}
```

## worker.parentPort
<!-- YAML
added: v10.5.0
Expand All @@ -72,6 +84,23 @@ using `worker.on('message')`, and messages sent from the parent thread
using `worker.postMessage()` will be available in this thread using
`parentPort.on('message')`.

```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);
});
}
```

## worker.threadId
<!-- YAML
added: v10.5.0
Expand All @@ -91,6 +120,19 @@ added: v10.5.0
An arbitrary JavaScript value that contains a clone of the data passed
to this thread’s `Worker` constructor.

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!'.
}
```

## Class: MessageChannel
<!-- YAML
added: v10.5.0
Expand Down Expand Up @@ -134,6 +176,20 @@ added: v10.5.0
The `'close'` event is emitted once either side of the channel has been
disconnected.

```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();
```

### Event: 'message'
<!-- YAML
added: v10.5.0
Expand All @@ -156,6 +212,9 @@ Disables further sending of messages on either side of the connection.
This method can be called when no further communication will happen over this
`MessagePort`.

The [`'close'` event][] will be emitted on both `MessagePort` instances that
are part of the channel.

### port.postMessage(value[, transferList])
<!-- YAML
added: v10.5.0
Expand All @@ -166,9 +225,28 @@ added: v10.5.0

Sends a JavaScript value to the receiving side of this channel.
`value` will be transferred in a way which is compatible with
the [HTML structured clone algorithm][]. In particular, it may contain circular
references and objects like typed arrays that the `JSON` API is not able
to stringify.
the [HTML structured clone algorithm][].

In particular, the significant differences to `JSON` are:
- `value` may contain circular references.
- `value` may contain instances of builtin JS types such as `RegExp`s,
`BigInt`s, `Map`s, `Set`s, etc.
- `value` may contained typed arrays, both using `ArrayBuffer`s
and `SharedArrayBuffer`s.
- `value` may contain [`WebAssembly.Module`][] instances.
- `value` may not contain native (C++-backed) objects other than `MessagePort`s.

```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);
```

`transferList` may be a list of `ArrayBuffer` and `MessagePort` objects.
After transferring, they will not be usable on the sending side of the channel
Expand All @@ -182,6 +260,30 @@ from either thread. They cannot be listed in `transferList`.
`value` may still contain `ArrayBuffer` instances that are not in
`transferList`; in that case, the underlying memory is copied rather than moved.

```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 ]);
```

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
Expand Down Expand Up @@ -215,6 +317,9 @@ Starts receiving messages on this `MessagePort`. When using this port
as an event emitter, this will be called automatically once `'message'`
listeners are attached.

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.

### port.unref()
<!-- YAML
added: v10.5.0
Expand Down Expand Up @@ -465,12 +570,14 @@ 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.

[`'close'` event]: #worker_threads_event_close
[`Buffer`]: buffer.html
[`EventEmitter`]: events.html
[`EventTarget`]: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget
[`MessagePort`]: #worker_threads_class_messageport
[`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
[`WebAssembly.Module`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module
[`Worker`]: #worker_threads_class_worker
[`cluster` module]: cluster.html
[`inspector`]: inspector.html
Expand Down

0 comments on commit a18b847

Please sign in to comment.