Spec-Zone.ru › Node.js 14 LTS

Потоки обработки задач

Устойчивость: 2 - Стабильно

Исходный код: lib/worker_threads.js

Модуль worker_threads позволяет использовать потоки, которые выполняют JavaScript параллельно. Для доступа к нему:

const worker = require('worker_threads');

Потоки (нити) полезны для выполнения ресурсоёмких операций JavaScript. Они не сильно помогут с операциями ввода-вывода. Встроенные асинхронные операции ввода-вывода Node.js более эффективны, чем потоки.

В отличие от child_process или cluster, worker_threads могут обмениваться памятью. Они делают это, передавая ArrayBuffer экземпляры или совместно используя экземпляры SharedArrayBuffer.

const {
  Worker, isMainThread, parentPort, workerData
} = require('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));
}

В приведенном выше примере для каждого вызова parse() запускается отдельный поток обработки задач. На практике для подобных задач лучше использовать пул потоков, иначе накладные расходы на создание потоков могут превысить их преимущества.

При реализации пула потоков используйте API AsyncResource для информирования средств диагностики (например, для предоставления асинхронных строк трассировки стека) о корреляции между задачами и их результатами. См. "Использование AsyncResource для пула потоков Worker" в документации async_hooks для примера реализации.

Потоки обработки задач по умолчанию наследуют параметры, не связанные с процессом. Обратитесь к Worker constructor options, чтобы узнать, как настроить параметры потоков обработки задач, в частности параметры argv и execArgv.

worker.isMainThread

Добавлен в: v10.5.0
  • <boolean>

Будет true в том случае, если этот код не выполняется внутри потока Worker.

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.markAsUntransferable(object)

Добавлен в: v14.5.0

Отметить объект как непередаваемый. Если object встречается в списке передачи вызова port.postMessage(), он будет проигнорирован.

В частности, это имеет смысл для объектов, которые можно клонировать, а не передавать, и которые используются другими объектами на стороне отправки. Например, Node.js помечает ArrayBuffer используемые для своего Buffer пула, этим способом.

Данную операцию отменить нельзя.

const { MessageChannel, markAsUntransferable } = require('worker_threads');

const pooledBuffer = new ArrayBuffer(8);
const typedArray1 = new Uint8Array(pooledBuffer);
const typedArray2 = new Float64Array(pooledBuffer);

markAsUntransferable(pooledBuffer);

const { port1 } = new MessageChannel();
port1.postMessage(typedArray1, [ typedArray1.buffer ]);

// The following line prints the contents of typedArray1 -- it still owns
// its memory and has been cloned, not transferred. Without
// `markAsUntransferable()`, this would print an empty Uint8Array.
// typedArray2 is intact as well.
console.log(typedArray1);
console.log(typedArray2);

В браузерах нет эквивалента этому API.

worker.moveMessagePortToContext(port, contextifiedSandbox)

Добавлен в: v11.13.0
  • port <MessagePort> Порт сообщений, который будет передан.

  • contextifiedSandbox <Object> Объект, подвергнутый контекстуализации, как возвращаемый методом vm.createContext().

  • Возвращает: <MessagePort>

Передать MessagePort в другой контекст vm. Исходный объект port станет непригодным, и возвращенный экземпляр MessagePort займет его место.

Возвращенный экземпляр MessagePort будет объектом в целевом контексте и унаследует от его глобального класса Object. Объекты, переданные слушателю port.onmessage(), также будут созданы в целевом контексте и унаследуют от его глобального класса Object.

Однако созданный экземпляр MessagePort больше не будет наследовать от EventTarget и для получения событий можно использовать только port.onmessage().

worker.parentPort

Добавлен в: v10.5.0
  • <null> | <MessagePort>

Если этот поток был запущен как Worker, это будет MessagePort, позволяющий обмениваться сообщениями с родительским потоком. Сообщения, отправленные с помощью parentPort.postMessage() будут доступны в родительском потоке с помощью worker.on('message'), а сообщения, отправленные из родительского потока с помощью worker.postMessage() будут доступны в этом потоке с помощью parentPort.on('message').

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.receiveMessageOnPort(port)

Добавлен в: v12.3.0
  • port <MessagePort>

  • Возвращает: <Object> | <undefined>

Получить одно сообщение из заданного MessagePort. Если сообщение недоступно, возвращается undefined, в противном случае возвращается объект со свойством message, содержащим полезную нагрузку сообщения, соответствующую самому старому сообщению в очереди MessagePort.

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

При использовании этой функции событие 'message' не будет отправлено, и слушатель onmessage не будет вызван.

worker.resourceLimits

Добавлен в: v13.2.0, v12.16.0
  • <Object>
    • maxYoungGenerationSizeMb <number>
    • maxOldGenerationSizeMb <number>
    • codeRangeSizeMb <number>
    • stackSizeMb <number>

Предоставляет набор ограничений ресурсов движка JS внутри потока обработки задач. Если параметр resourceLimits был передан конструктору Worker, это совпадает с его значениями.

Если это используется в главном потоке, его значение — пустой объект.

worker.SHARE_ENV

Добавлен в: v11.14.0
  • <symbol>

Особое значение, которое можно передать в качестве параметра env конструктора Worker, чтобы указать, что текущий поток и поток обработки задач должны совместно использовать чтение и запись для одного набора переменных среды.

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'.
  });

worker.threadId

Добавлен в: v10.5.0
  • <integer>

Целочисленный идентификатор текущего потока. В соответствующем объекте потока (если он есть), он доступен как worker.threadId. Это значение уникально для каждого экземпляра Worker внутри одного процесса.

worker.workerData

Добавлен в: v10.5.0

Произвольное значение JavaScript, которое содержит клон данных, переданных конструктору этого потока Worker.

Данные клонируются так же, как если бы использовался postMessage(), в соответствии с алгоритмом структурированного клонирования HTML.

const { Worker, isMainThread, workerData } = require('worker_threads');

if (isMainThread) {
  const worker = new Worker(__filename, { workerData: 'Hello, world!' });
} else {
  console.log(workerData);  // Prints 'Hello, world!'.
}

Класс: MessageChannel

Добавлен в: v10.5.0

Экземпляры класса worker.MessageChannel представляют собой асинхронный двусторонний канал связи. У класса MessageChannel нет собственных методов. new MessageChannel() возвращает объект со свойствами port1 и port2, которые ссылаются на связанные экземпляры MessagePort.

const { MessageChannel } = require('worker_threads');

const { port1, port2 } = new MessageChannel();
port1.on('message', (message) => console.log('received', message));
port2.postMessage({ foo: 'bar' });
// Prints: received { foo: 'bar' } from the `port1.on('message')` listener

Класс: MessagePort

История
Версия Изменения
v14.7.0

Этот класс теперь наследуется от EventTarget вместо EventEmitter.

v10.5.0

Добавлен в: v10.5.0

  • Расширяет: <EventTarget>

Экземпляры класса worker.MessagePort представляют собой один конец асинхронного двустороннего канала связи. Он может использоваться для передачи структурированных данных, областей памяти и других MessagePort между различными потоками Worker.

Эта реализация соответствует браузерным MessagePort.

Событие: 'close'

Добавлен в: v10.5.0

Событие 'close' генерируется, когда любая сторона канала разрывается.

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

Событие: 'message'

Добавлен в: v10.5.0
  • value <любой> Переданное значение

Событие 'message' генерируется для любого входящего сообщения, содержащего клонированный ввод из port.postMessage().

Обработчики этого события получат клон параметра value в качестве входных данных postMessage() и без дополнительных аргументов.

Событие: 'messageerror'

Добавлен в: v14.5.0
  • error <Ошибка> Объект Error

Событие 'messageerror' генерируется, когда произошла ошибка при десериализации сообщения.

В настоящее время это событие генерируется, когда возникла ошибка при создании объекта JS, отправленного на принимающую сторону. Такие ситуации редки, но могут произойти, например, когда некоторые объекты API Node.js получены в vm.Context (где API Node.js в настоящее время недоступны).

port.close()

Добавлен в: v10.5.0

Отключает дальнейшую отправку сообщений с любой стороны соединения. Этот метод может быть вызван, когда больше нет необходимости в коммуникации через этот MessagePort.

Событие 'close' будет сгенерировано на обоих экземплярах MessagePort в канале.

port.postMessage(value[, transferList])

История
Версия Изменения
v14.5.0

Добавлен KeyObject в список клонируемых типов.

v14.5.0

Добавлен FileHandle в список передаваемых типов.

v10.5.0

Добавлен в: v10.5.0

  • value <любой>
  • transferList <Массив объектов>

Отправляет JavaScript-значение на принимающую сторону канала. value будет передано совместимым с алгоритмом структурированного клонирования HTML способом.

Существенные различия с JSON:

  • value может содержать циклические ссылки.
  • value может содержать экземпляры встроенных JS-типов, таких как RegExpы, BigIntы, Mapы, Setы и т.д.
  • value может содержать массивы с типом, как с использованием ArrayBuffer и SharedArrayBuffer.
  • value может содержать экземпляры WebAssembly.Module.
  • value не может содержать нативные (поддерживаемые C++) объекты, кроме MessagePortов, FileHandleов и KeyObjectов.
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 может быть списком ArrayBuffer, MessagePort и FileHandle объектов. После передачи они больше не будут доступны на стороне отправки канала (даже если они не содержатся в value). В отличие от дочерних процессов, передача дескрипторов, таких как сетевые сокеты, в настоящее время не поддерживается.

Если value содержит экземпляры SharedArrayBuffer, они будут доступны в любом потоке. Они не могут быть перечислены в transferList.

value может по-прежнему содержать экземпляры ArrayBuffer, которые не находятся в transferList; в этом случае базовое содержимое копируется, а не перемещается.

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

Из-за использования алгоритма структурированного клонирования для копирования объектов, неперечисляемые свойства, обработчики доступа к свойствам и прототипы объектов не сохраняются. В частности, объекты Buffer будут читаться как обычные Uint8Array на принимающей стороне.

Объект сообщения будет немедленно клонирован и может быть изменён после отправки без побочных эффектов.

Дополнительную информацию о механизмах сериализации и десериализации, стоящих за этим API, см. в API сериализации модуля v8.

Рекомендации по передаче TypedArrays и буферов

Все экземпляры TypedArray и Buffer представляют собой представления базового ArrayBuffer объекта. То есть, ArrayBuffer фактически хранит исходные данные, а TypedArray и Buffer объекты предоставляют способ просмотра и обработки данных. Возможна и часто встречается ситуация, когда несколько представлений создаются для одного экземпляра ArrayBuffer объекта. Необходимо быть очень внимательным при использовании списка передачи для передачи ArrayBuffer, поскольку это сделает все TypedArray и Buffer экземпляры, использующие тот же самый ArrayBuffer объект, недоступными.

const ab = new ArrayBuffer(10);

const u1 = new Uint8Array(ab);
const u2 = new Uint16Array(ab);

console.log(u2.length);  // prints 5

port.postMessage(u1, [u1.buffer]);

console.log(u2.length);  // prints 0

В частности, для экземпляров Buffer вопрос о передаче или клонировании базового ArrayBuffer зависит исключительно от способа создания экземпляра, что часто невозможно надёжно определить.

Экземпляр ArrayBuffer может быть помечен с помощью markAsUntransferable(), чтобы указать, что он всегда должен клонироваться, а не передаваться.

В зависимости от способа создания экземпляра Buffer, он может или не может владеть своим базовым ArrayBuffer. Экземпляр ArrayBuffer не должен передаваться, если не известно, что экземпляр Buffer владеет им. В частности, для экземпляров Buffer из внутреннего пула Buffer (например, с использованием Buffer.from() или Buffer.alloc()) передача невозможна, и они всегда будут клонироваться, что отправляет копию всего пула Buffer. Это поведение может привести к неоправданному увеличению использования памяти и потенциальным проблемам безопасности.

См. Buffer.allocUnsafe() для получения более подробной информации о пуле Buffer.

Экземпляры ArrayBuffer для экземпляров Buffer, созданных с использованием Buffer.alloc() или Buffer.allocUnsafeSlow(), всегда могут быть переданы, но это сделает все другие существующие представления этих ArrayBuffer экземпляров непригодными для использования.

port.ref()

Добавлен в: v10.5.0

Противное действие unref(). Вызов ref() для предварительно unref() портированного порта не позволит программе завершиться, если это единственная активная ссылка (стандартное поведение). Если порт ref()рован, повторный вызов ref() не произведёт никакого действия.

Если обработчики прикреплены или удалены с помощью .on('message'), порт будет ref()рован и unref()рован автоматически, в зависимости от наличия обработчиков для события.

port.start()

Добавлен в: v10.5.0

Начинает приём сообщений через этот MessagePort. При использовании порта в качестве генератора событий это будет автоматически вызываться после прикрепления обработчиков 'message'.

Этот метод нужен для соответствия API веб-MessagePort API. В Node.js он полезен только для игнорирования сообщений, когда нет обработчиков событий. В Node.js также отличается обработкой .onmessage. Установка его автоматически вызывает .start(), но снятие установки позволяет сообщениям накапливаться до тех пор, пока не будет установлен новый обработчик или порт не будет удалён.

port.unref()

Добавлен в: v10.5.0

Вызов unref() для порта позволит потоку завершиться, если это единственная активная ссылка в системе событий. Если порт уже unref()рован, повторный вызов unref() не произведёт никакого действия.

Если обработчики прикреплены или удалены с помощью .on('message'), порт будет ref()рован и unref()рован автоматически, в зависимости от наличия обработчиков для события.

Класс: Worker

Добавлен в: v10.5.0
  • Расширяет: <EventEmitter>

Класс Worker представляет собой независимую JavaScript-поток выполнения. Большинство API Node.js доступны внутри него.

Существенные отличия в среде Worker:

  • Поток ввода-process.stdin, вывода-process.stdout и стандартной ошибки-process.stderr могут быть перенаправлены родительским потоком.
  • Свойство require('worker_threads').isMainThread установлено в false.
  • Доступен порт сообщения require('worker_threads').parentPort.
  • process.exit() не останавливает всю программу, а только текущий поток, и process.abort() недоступен.
  • process.chdir() и методы process, устанавливающие идентификаторы групп или пользователей, недоступны.
  • process.env — это копия переменных среды родительского потока, если не указано иное. Изменения в одной копии не будут видны в других потоках и не будут видны нативным дополнениям (если worker.SHARE_ENV был передан в качестве env параметра конструктору Worker).
  • process.title изменить нельзя.
  • Сигналы не будут доставлены через process.on('...').
  • Выполнение может остановиться в любой момент в результате вызова worker.terminate().
  • Каналы IPC от родительских процессов недоступны.
  • Модуль trace_events не поддерживается.
  • Нативные дополнения могут быть загружены только из нескольких потоков, если они удовлетворяют определенным условиям.

Создание экземпляров Worker внутри других Worker возможно.

Как и Web Workers и модуль cluster, двустороннее взаимодействие может быть достигнуто посредством межпотоковой передачи сообщений. Внутри Worker есть встроенная пара MessagePort, которые связаны друг с другом при создании Worker. Хотя объект MessagePort на стороне родительского потока не экспонируется напрямую, его функциональность экспонируется через worker.postMessage() и событие worker.on('message') на объекте Worker для родительского потока.

Для создания пользовательских каналов связи (что рекомендуется вместо использования глобального канала, так как это способствует разделению ответственности), пользователи могут создать объект MessageChannel в любом потоке и передать один из MessagePort в этом MessageChannel в другой поток через существующий канал, например, глобальный.

См. port.postMessage() для получения дополнительной информации о передаче сообщений и о том, какие JavaScript-значения могут быть успешно переданы через барьер потоков.

const assert = require('assert');
const {
  Worker, MessageChannel, MessagePort, isMainThread, parentPort
} = require('worker_threads');
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 {
  parentPort.once('message', (value) => {
    assert(value.hereIsYourPort instanceof MessagePort);
    value.hereIsYourPort.postMessage('the worker is sending this');
    value.hereIsYourPort.close();
  });
}

new Worker(filename[, options])

История
Версия Изменения
v14.9.0

Параметр filename может быть объектом WHATWG URL с использованием протокола data:.

v14.9.0

Параметр trackUnmanagedFds по умолчанию был установлен в true.

v14.6.0

Был добавлен параметр trackUnmanagedFds.

v14.0.0

Был добавлен параметр transferList.

v13.12.0

Параметр filename может быть объектом WHATWG URL с использованием протокола file:.

v13.4.0, v12.16.0

Был добавлен параметр argv.

v13.2.0, v12.16.0

Был добавлен параметр resourceLimits.

v10.5.0

Добавлен в: v10.5.0

  • filename <строка> | <URL> Путь к главному скрипту или модулю Рабочего потока. Должен быть либо абсолютным, либо относительным путём (относительно текущего каталога), начинающимся с ./ или ../, или объектом WHATWG URL , использующим протокол file: или data:. При использовании data: URL, данные интерпретируются на основе MIME-типа с использованием загрузчика модулей ECMAScript data:. Если options.eval равно true, это строка, содержащая код JavaScript, а не путь.
  • options <Объект>
    • argv <массив любых типов> Список аргументов, которые будут сериализованы в строку и добавлены к process.argv в рабочем потоке. Это в основном похоже на workerData, но значения будут доступны в глобальном process.argv как если бы они были переданы в качестве командной строки параметрам скрипта.
    • env <Объект> Если установлено, задаёт начальное значение process.env внутри потока Рабочего потока. В качестве специального значения может использоваться worker.SHARE_ENV, чтобы указать, что родительский и дочерний потоки должны разделять свои переменные среды; в этом случае изменения в объекте process.env одного потока будут влиять на другой поток. По умолчанию: process.env.
    • eval <логическое значение> Если true и первый аргумент – string, интерпретировать первый аргумент конструктора как скрипт, который выполняется после того, как рабочий поток будет запущен.
    • execArgv <массив строк> Список опций командной строки узла, переданных рабочему потоку. Опции V8 (например, --max-old-space-size) и опции, которые влияют на процесс (например, --title) не поддерживаются. Если установлено, это будет предоставлено как process.execArgv внутри рабочего потока. По умолчанию, опции будут унаследованы от родительского потока.
    • stdin <логическое значение> Если это установлено в true, то worker.stdin предоставит поток для записи, содержимое которого будет отображаться как process.stdin внутри Рабочего потока. По умолчанию данные не предоставляются.
    • stdout <логическое значение> Если это установлено в true, тогда worker.stdout не будет автоматически перенаправлен в process.stdout в родительском потоке.
    • stderr <логическое значение> Если это установлено в true, тогда worker.stderr не будет автоматически перенаправлен в process.stderr в родительском потоке.
    • workerData <любой тип> Любое значение JavaScript, которое будет клонировано и сделано доступным как require('worker_threads').workerData. Клонирование будет происходить в соответствии с алгоритмом HTML structured clone algorithm, и будет выброшено исключение, если объект не может быть клонирован (например, если он содержит function).
    • trackUnmanagedFds <логическое значение> Если это установлено в true, то Рабочий поток будет отслеживать сырые дескрипторы файлов, управляемые через fs.open() и fs.close(), и закроет их при завершении Рабочего потока, подобно другим ресурсам, таким как сетевые сокеты или дескрипторы файлов, управляемые через FileHandle API. Эта опция автоматически наследуется всеми вложенными Worker. По умолчанию: false.
    • transferList <массив объектов> Если один или несколько объектов типа MessagePort передаются в workerData, для этих элементов требуется transferList, в противном случае будет выброшено исключение ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST. Дополнительная информация доступна в port.postMessage().
    • resourceLimits <Объект> Необязательный набор ограничений ресурсов для новой инстанции движка JS. При достижении этих ограничений произойдёт завершение инстанции Worker. Эти ограничения влияют только на движок JS и не затрагивают внешние данные, включая ArrayBuffer. Даже если эти ограничения установлены, процесс может быть прерван, если он столкнётся с глобальной ситуацией недостатка памяти.
      • maxOldGenerationSizeMb <число> Максимальный размер основного куска памяти в МБ.
      • maxYoungGenerationSizeMb <число> Максимальный размер куска памяти для недавно созданных объектов.
      • codeRangeSizeMb <число> Размер предварительно выделенного диапазона памяти, используемого для сгенерированного кода.
      • stackSizeMb <число> Максимальный размер стека по умолчанию для потока. Малые значения могут привести к неработоспособности экземпляров Рабочего потока. По умолчанию: 4.

Событие: 'error'

Добавлен в: v10.5.0
  • err <Ошибка>

Событие 'error' генерируется, если поток Рабочего потока выбрасывает необработанное исключение. В этом случае Рабочий поток будет завершён.

Событие: 'exit'

Добавлен в: v10.5.0
  • exitCode <целое число>

Событие 'exit' генерируется, когда Рабочий поток останавливается. Если Рабочий поток завершился вызовом process.exit(), параметр exitCode будет содержать возвращённый код выхода. Если Рабочий поток был завершён, параметр exitCode будет 1.

Это последнее событие, генерируемое любой инстанцией Worker.

Событие: 'message'

Добавлен в: v10.5.0
  • value <любой тип> Переданное значение

Событие 'message' генерируется, когда поток Рабочего потока вызывает require('worker_threads').parentPort.postMessage(). Подробнее см. событие port.on('message').

Все сообщения, отправленные из потока Рабочего потока, будут сгенерированы до генерации события 'exit' объекта Worker.

Событие: 'messageerror'

Добавлен в: v14.5.0
  • error <Объект ошибки> Объект Error

Событие 'messageerror' генерируется при ошибке десериализации сообщения.

Событие: 'online'

Добавлен в: v10.5.0

Событие 'online' генерируется, когда поток Рабочего потока начинает выполнение кода JavaScript.

worker.getHeapSnapshot()

Добавлен в: v13.9.0
  • Возвращает: <Promise> Promise для потока чтения, содержащего снимок куска памяти V8

Возвращает поток чтения для снимка куска памяти V8 текущего состояния Рабочего потока. Подробнее см. v8.getHeapSnapshot().

Если поток Рабочего потока больше не работает, что может произойти до генерации события 'exit', возвращаемое Promise будет немедленно отклонено с ошибкой ERR_WORKER_NOT_RUNNING.

worker.performance

Добавлен в: v14.17.0

Объект, который можно использовать для запроса информации о производительности из экземпляра Рабочего потока. Аналогичен perf_hooks.performance.

performance.eventLoopUtilization([utilization1[, utilization2]])
Добавлен в: v14.17.0
  • utilization1 <Объект> Результат предыдущего вызова eventLoopUtilization().
  • utilization2 <Объект> Результат предыдущего вызова eventLoopUtilization() до utilization1.
  • Возвращает <Объект>
    • idle <число>
    • active <число>
    • utilization <число>

Такой же вызов, как perf_hooks eventLoopUtilization(), за исключением того, что возвращаются значения экземпляра потока.

Одно отличие заключается в том, что, в отличие от основного потока, запуск внутри потока выполняется в цикле событий. Таким образом, использование цикла событий будет доступно сразу после начала выполнения скрипта потока.

Время idle, которое не увеличивается, не указывает на то, что поток застрял на этапе запуска. Приведенные примеры показывают, как общее время жизни потока никогда не накопит времени idle, но все же сможет обрабатывать сообщения.

const { Worker, isMainThread, parentPort } = require('worker_threads');

if (isMainThread) {
  const worker = new Worker(__filename);
  setInterval(() => {
    worker.postMessage('hi');
    console.log(worker.performance.eventLoopUtilization());
  }, 100).unref();
  return;
}

parentPort.on('message', () => console.log('msg')).unref();
(function r(n) {
  if (--n < 0) return;
  const t = Date.now();
  while (Date.now() - t < 300);
  setImmediate(r, n);
})(10);

Использование цикла событий потоком доступно только после того, как будет выброшено событие 'online', и если оно вызывается до этого или после события 'exit', все свойства имеют значение 0.

worker.postMessage(value[, transferList])

Добавлена в: v10.5.0
  • value <любой>
  • transferList <Массив объектов>

Отправить сообщение в поток, которое будет получено через require('worker_threads').parentPort.on('message'). Дополнительные сведения см. в port.postMessage().

worker.ref()

Добавлена в: v10.5.0

Обратное действие unref(), вызов ref() для ранее unref() потока не позволит программе завершиться, если это единственная активная ссылка (по умолчанию). Если поток ref()ен, вызов ref() не повлияет.

worker.resourceLimits

Добавлена в: v13.2.0, v12.16.0
  • <Объект>
    • maxYoungGenerationSizeMb <число>
    • maxOldGenerationSizeMb <число>
    • codeRangeSizeMb <число>
    • stackSizeMb <число>

Предоставляет набор ограничений ресурсов движка JS для этого потока Worker. Если опция resourceLimits была передана конструктору Worker, это соответствует ее значениям.

Если поток остановлен, возвращаемое значение — пустой объект.

worker.stderr

Добавлена в: v10.5.0
  • <stream.Readable>

Это поток чтения, содержащий данные, записанные в process.stderr внутри потока Worker. Если stderr: true не передавалась конструктору Worker, данные будут направлены в поток process.stderr родительского потока.

worker.stdin

Добавлена в: v10.5.0
  • <null> | <stream.Writable>

Если stdin: true передавалась конструктору Worker, это поток записи. Данные, записанные в этот поток, будут доступны в потоке Worker как process.stdin.

worker.stdout

Добавлена в: v10.5.0
  • <stream.Readable>

Это поток чтения, содержащий данные, записанные в process.stdout внутри потока Worker. Если stdout: true не передавалась конструктору Worker, данные будут направлены в поток process.stdout родительского потока.

worker.terminate()

История
Версия Изменения
v12.5.0

Теперь эта функция возвращает Promise. Передача обратного вызова устарела и была бесполезна до этой версии, так как поток Worker фактически завершался синхронно. Теперь завершение — полностью асинхронная операция.

v10.5.0

Добавлена в: v10.5.0

  • Возвращает: <Promise>

Останавливает выполнение всего JavaScript в потоке Worker как можно быстрее. Возвращает Promise для кода выхода, который выполняется, когда выброшено событие 'exit'.

worker.threadId

Добавлена в: v10.5.0
  • <целое число>

Целочисленный идентификатор для указанного потока. Внутри потока Worker он доступен как require('worker_threads').threadId. Это значение уникально для каждого экземпляра Worker внутри одного процесса.

worker.unref()

Добавлена в: v10.5.0

Вызов unref() для потока позволит потоку завершиться, если это единственная активная ссылка в системе событий. Если поток уже unref()ен, вызов unref() не повлияет.

Примечания

Запуск потоков Worker из скриптов предварительной загрузки

Обращайте внимание при запуске потоков Worker из скриптов предварительной загрузки (скриптов, загруженных и выполненных с помощью флага командной строки -r). Если опция execArgv не задана явно, новые потоки Worker автоматически наследуют флаги командной строки от выполняющегося процесса и будут предварительно загружать те же скрипты предварительной загрузки, что и основной поток. Если скрипт предварительной загрузки безусловно запускает поток Worker, каждый созданный поток будет запускать еще один, пока приложение не завершится аварийно.

© Joyent, Inc. and other Node contributors
Licensed under the MIT License.
Node.js is a trademark of Joyent, Inc. and is used with its permission.
We are not endorsed by or affiliated with Joyent.
https://nodejs.org/dist/latest-v14.x/docs/api/worker_threads.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API