Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc: improve worker_threads documentation #26110

Closed
wants to merge 4 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 99 additions & 2 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, with message channels between them. To access it:
addaleax marked this conversation as resolved.
Show resolved Hide resolved

```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,16 @@ added: v10.5.0
An arbitrary JavaScript value that contains a clone of the data passed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be good to include more of a description of what "clone" here means in general. I know there are a few bits and pieces of an explanation through the doc, but coalescing those into a single section with some information on what types of values cannot be cloned, would be good.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jasnell How does 919fd07 sound to you?

to this thread’s `Worker` constructor.

```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 +173,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 +209,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
Copy link
Member

@Trott Trott Feb 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be I'm over-reacting to passive voice, but perhaps this?:

Both `MessagePort` instances that are part of the channel will emit a [`'close'` event][].

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have to admit that active voice sounds a bit weird to me when referring to events :)

are part of the channel.

### port.postMessage(value[, transferList])
<!-- YAML
added: v10.5.0
Expand All @@ -170,6 +226,19 @@ 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.


```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
anymore (even if they are not contained in `value`). Unlike with
Expand All @@ -182,6 +251,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':
addaleax marked this conversation as resolved.
Show resolved Hide resolved
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
addaleax marked this conversation as resolved.
Show resolved Hide resolved
// 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 +308,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 @@ -472,6 +568,7 @@ active handle in the event system. If the worker is already `unref()`ed calling
[`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
[`Worker`]: #worker_threads_class_worker
[`'close'` event]: #worker_threads_event_close
addaleax marked this conversation as resolved.
Show resolved Hide resolved
[`cluster` module]: cluster.html
[`inspector`]: inspector.html
[`port.on('message')`]: #worker_threads_event_message
Expand Down