我正在尝试使用子进程在node.js上实现并行处理。 基本上我希望我的代码:
最后,打印更改后的完整对象。
我不得不面对几个问题,首先是使用多个.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可能是更好的方法,但我认为它们仍处于试验阶段。 谢谢!