Выполнить функцию JavaScript в параллельном модуле - PullRequest
0 голосов
/ 03 октября 2019

Вопрос формализован следующим образом.

Можем ли мы вызвать непрозрачную функцию в другом потоке в javascript и получить обещание?

Одна из возможных реализацийэта функция.

function executeAsync(f: function, ...args);

1. Javascript runtime spawns 1 parallel unit (thread, coroutine, etc).

2. Javascript runtime executes the function f in parallel. (Ignore data race issue, maybe add mutex later)

3. After the parallel unit has done its job. Remove the parallel unit from the pool and resolve the Promise. (put callback into the callback queue)

Пожалуйста, прокомментируйте, если у вас все еще есть какие-либо сомнения. Спасибо

ЗА ССЫЛКАМИ

Приведенный ниже код служит аналогичной цели, но не работает для не чистой функции Используется safe-eval модуль узла, который оценивает строку и конвертирует ее в функцию JavaScript

const {isMainThread, Worker, workerData, parentPort} = require("worker_threads");
const {safeEval} = require("safe-eval");
if (isMainThread) {
  // functionObject must be pure function
  module.exports = {executeAsync: function(functionObject = function(...paramsObject) {return undefined;}, ...paramsObject) {
    return new Promise(function(resolve, reject) {
      const worker = new Worker(__filename, {
        workerData: {
          functionString: functionObject.toString(),
          argumentsObject: paramsObject,
        }
      });
      worker.on("message", resolve);
      worker.on("error", reject);
      worker.on("exit", function(functionObject) {
        if (functionObject != 0) {
          reject(new Error(`Worker stopped with code ${functionObject}`));
        }
      });
    });
  }};
} else {
  const {functionString, argumentsObject} = workerData;
  const functionObject = safeEval(functionString);
  parentPort.postMessage(functionObject(...argumentsObject));
}

1 Ответ

1 голос
/ 06 октября 2019

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

Это распространенное заблуждение. Обещания не делают что-то синхронное асинхронным. Это просто стандартизированный способ наблюдения того, что уже асинхронно. Единственное асинхронное поведение, которое они сами обеспечивают, заключается в том, что когда вы регистрируете обработчик через .then (или .catch или .finally), вы гарантируете, что этот обработчик будет вызываться асинхронно, а не синхронно, даже если обещание ужеулажен. И даже тогда это асинхронный , а не параллельный . Обратный вызов происходит в том же потоке, чуть позже.

Единственный способ получить действительно параллельную обработку в JavaScript на основе браузера - это использовать веб-работников , на которых моделируются работники Node.js. ,Как вы сказали, , в основном , означает, что вам нужен отдельный файл для кода, который будет выполняться на рабочем месте, хотя можно использовать строку .


¹ «единственный путь» - ну, технически отдельные независимые вкладки могут в конечном итоге работать в разных потоках, но только если они созданы совершенно независимо. Если одна вкладка открывает другую, они будут использовать один и тот же поток, поскольку у каждой из них есть ссылка на другую.

...