处理对子进程的多个请求的请求:如何进行?

时间:2019-04-23 16:48:47

标签: node.js promise child-process

我正在尝试使用子进程在node.js上实现并行处理。 基本上我希望我的代码:

  • 创建一些子进程
  • 在具有多行的对象之间循环,然后根据其类型(带有承诺)将每一行发送给子进程
  • 在子进程上,睡一会儿(以模拟较重的计算),更改接收到的代码,然后将其发送回主线程
  • 回到主线程,接收更改后的行,将其存储并解决相应的promise。

最后,打印更改后的完整对象。

我不得不面对几个问题,首先是使用多个.on(“ message”)侦听器,然后是使用Promise解析-我仍然有:

index.js

var obj = {"rows":[{"type":"A","value":1},{"type":"A","value":500},{"type":"A","value":1000},{"type":"B","value":0},{"type":"C","value":50}]}

const alter = (obj) => {

  let promises = [];

  const { fork } = require('child_process');
  const workerA = fork("./worker.js", ["A"]);
  const workerB = fork("./worker.js", ["B"]);
  const workerC = fork("./worker.js", ["C"]);

  global.obj = obj;

  const MessageToWorker = (worker, msg) => {
    return new Promise((resolve,reject) => {
      function handleComm(msg){
        worker.removeListener("message", handleComm);
        console.log(`Received answer for row ${msg.index}, value ${msg.row.value}`);
        global.obj.rows[msg.index] = msg.row;
        resolve();
      }
      worker.send(msg);
      worker.on("message",handleComm);
    });
  }

  rowsLength = obj.rows.length;
  for (let rowIndex = 0; rowIndex < rowsLength; rowIndex++){
    row = obj.rows[rowIndex];

    switch (row.type){
      case "A":
        console.log(`A detected for row ${rowIndex}`);
        promises.push(MessageToWorker(workerA,{row: row, to_add: 1, index: rowIndex, sleep: Math.round(Math.random()*1000+1000)}));
        break;
      case "B":
        console.log(`B detected for row ${rowIndex}`);
        promises.push(MessageToWorker(workerB,{row: row, to_add: 2, index: rowIndex, sleep: Math.round(Math.random()*1000+1000)}));
        break;
      case "C":
        console.log(`C detected for row ${rowIndex}`);
        promises.push(MessageToWorker(workerC,{row: row, to_add: 3, index: rowIndex, sleep: Math.round(Math.random()*1000+1000)}));
        break;
    }
  }

  return promises; 
}


const one = async(obj) => {
  console.time("TASK: ");
  await Promise.all(alter(obj));
  obj = global.obj;
  console.timeEnd("TASK: ");
  console.log(obj);
}

one(obj);

worker.js

const myName = process.argv[2];

console.log(`[${myName}] -  Alive`);

function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

process.on('message', async (message) => {
    console.log(`[${myName}] -  Received row ${message.index}`);

    console.log(`[${myName}] -  I'll sleep for ${message.sleep}ms`);
    await delay(message.sleep);
    console.log(`[${myName}] -  I'm awake`)

    let row = message.row;
    let to_add = message.to_add;

    console.log(`[${myName}] -  Altering value ${row.value}`);
    row.value = row.value + to_add;
    console.log(`[${myName}] -  Value changed to ${row.value}`);

    process.send({row: row, index: message.index});
});

这是示例输出:

A detected for row 0
A detected for row 1
A detected for row 2
B detected for row 3
C detected for row 4
[A] -  Alive
[A] -  Received row 0
[A] -  I'll sleep for 1817ms
[B] -  Alive
[A] -  Received row 1
[A] -  I'll sleep for 1232ms
[A] -  Received row 2
[A] -  I'll sleep for 1707ms
[B] -  Received row 3
[B] -  I'll sleep for 1062ms
[C] -  Alive
[C] -  Received row 4
[C] -  I'll sleep for 1345ms
[B] -  I'm awake
[B] -  Altering value 0
[B] -  Value changed to 5
Received answer for row 3, value 5
[A] -  I'm awake
[A] -  Altering value 500
[A] -  Value changed to 501
Received answer for row 1, value 501
Received answer for row 1, value 501
Received answer for row 1, value 501
[C] -  I'm awake
[C] -  Altering value 50
[C] -  Value changed to 250
Received answer for row 4, value 250
TASK: : 1437.319ms
{ rows:
   [ { type: 'A', value: 1 },
     { type: 'A', value: 501 },
     { type: 'A', value: 1000 },
     { type: 'B', value: 5 },
     { type: 'C', value: 250 } ] }
[A] -  I'm awake
[A] -  Altering value 1000
[A] -  Value changed to 1001
[A] -  I'm awake
[A] -  Altering value 1
[A] -  Value changed to 2

问题显然与第一个工作人员有关:在取回值之前我叫了三遍,而当我返回第一个工作时,所有的诺言似乎都立即解决了(三行“收到第一行的答案” ,值501“行)。 因此,主脚本认为它已经完成了。

您能帮我解决这个问题吗? 我知道worker threads可能是更好的方法,但我认为它们仍处于试验阶段。 谢谢!

0 个答案:

没有答案