Встроенные дочерние процессы в Node.js - PullRequest
0 голосов
/ 15 мая 2018

Я знаком с Web Workers в браузере и понял, что Node.js эквивалентен

const worker = new Worker('./worker')

есть

const worker = child_process.fork('./worker')

API немного отличается, и они не совсем работают одинаково, но в итоге Web Workers и дочерние процессы, похоже, делают примерно одно и то же; позволяют запускать код JavaScript параллельно.

Теперь есть одна изящная вещь, которую можно сделать с Web Workers, где вместо создания Worker путем передачи пути / URL-адреса файла, содержащего рабочий код, вы можете передать фактическую функцию. Это может быть достигнуто с помощью этой простой трехстрочной функции:

function createWorker(fn) {
  var blob = new Blob(['self.onmessage = ', fn.toString()], { type: 'text/javascript' });
  var url = URL.createObjectURL(blob);

  return new Worker(url);
}

Это позволяет вам записать ваш рабочий код в файл main / master / parent (как вы хотите это называть), например:

var myWorker = createWorker(function (e) {
  self.postMessage(e.data.toUpperCase());
});

myWorker.onMessage = function (e) {
  console.log(e.data); // HELLO FROM AN INLINE WORKER!
}

myWorker.postMessage('hello from an inline worker!')

ВОПРОС
Как я могу добиться того же с помощью дочерних процессов Node.js? Из документации я не мог понять, можно ли передать в child_process.fork что-то кроме пути к модулю или есть какой-то другой способ добиться того, чего я хочу; писать встроенные дочерние процессы.

UPDATE
Я попробовал следующее, основываясь на предложении @Bergi в комментариях:

const fileSync = require('tmp').fileSync;
const writeFileSync = require('fs').writeFileSync;
const fork = require('child_process').fork;

function createWorker(fn) {
  const tmpobj = fileSync();
  writeFileSync(tmpobj.name, fn.toString()); 

  return fork(tmpobj.name);
}

var myWorker = createWorker(function (e) {
  process.send(e.toUpperCase());
});

myWorker.on('message', function (e) {
  console.log(e); // HELLO FROM AN INLINE WORKER!
})

myWorker.send('hello from an inline worker!');

Увы, я получаю следующую ошибку:

C:\Users\phili\AppData\Local\Temp\tmp-165566BgqUKKM5yjR.tmp:1
(function (exports, require, module, __filename, __dirname) { function (e) {
                                                                       ^

SyntaxError: Unexpected token (
    at createScript (vm.js:80:10)
    at Object.runInThisContext (vm.js:139:10)
    at Module._compile (module.js:616:28)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Function.Module.runMain (module.js:693:10)
    at startup (bootstrap_node.js:188:16)
    at bootstrap_node.js:609:3

Боюсь, я здесь не в себе. Любая идея, что происходит и как я могу заставить его работать?

1 Ответ

0 голосов
/ 15 мая 2018

Вот что у меня получилось:

const fileSync = require('tmp').fileSync;
const writeFileSync = require('fs').writeFileSync;
const fork = require('child_process').fork;



function createWorker(fn) {
  const tmpobj = fileSync();
  writeFileSync(tmpobj.name, `process.on('message', ${fn.toString()})`); 

  return fork(tmpobj.name);
}

var myWorker = createWorker(function (e) {
  process.send(e.toUpperCase());
});

myWorker.on('message', function (e) {
  console.log(e); // HELLO FROM AN INLINE WORKER!
})

myWorker.send('hello from an inline worker!');

Миллион благодарностей @Bergi за помощь в выяснении этого.

...