我目前正在使用子进程,以便以非阻塞方式运行某些计算功能。
我遇到了一个问题,我需要能够将计算结果与父进程中的正确回调联系起来。例如:
var cp = require('child_process');
var n = cp.fork(__dirname + '/child.js');
exports.evaluate = function(data, callback) {
n.send({ data : data});
n.once('message', function(result) {
callback(result);
}
}
这个例子的问题是,如果一个计算在另一个计算之前返回,那么它将不会收到正确的结果。
有没有办法使用自定义事件名称而不是'message'来确保每次调用evaluate函数时都会创建一个唯一的侦听器,一旦调用它就会被删除?
如何使用子进程发出自定义事件?
提前致谢!
答案 0 :(得分:5)
使用new events.EventEmitter
创建一个新的EventEmitter。然后根据您收到eventType:"someType"
的任何邮件发出事件。
即。
之类的东西 events = require("events")
emitter = new events.EventEmitter
n.on("message", function(msg) { emitter.emit(msg.eventType,msg.body) })
然后将侦听器(使用once
或on
)绑定到该事件发射器。
答案 1 :(得分:0)
我认为一种不错的方法可能是递归调用您的evaluate函数,直到所有计算完成。使用队列进行计算并以FIFO方式处理它们。
var computations = [];
你需要抛弃n.once('消息'并且在你的evalutate函数之外定义一个n.on('消息'处理程序。使用每个'消息&# 39;您收到的符合您的评估数据类型(让我们称之为'结果')然后您将该结果保存在结果的FIFO队列中。之后,您将' ; d检查是否有更多的计算,并再次调用evaluate。如果你愿意的话,可以清理它,以便在evaluate函数中拼掉最旧的计算。
var results = [];
n.on('message', function(m) {
if(m.msg === "result") { // message looks like {msg: "result", data: 1234}
results.push(m.data);
}
if(computations.length > 0) {
var comp = computations[0]; // Save oldest computation
computations.splice(0,1); // Remove oldest computation from array
evaluate(comp); // Evaluate oldest computation
}
else
process_results(); // if you have 0 computations left,
// you got the last result so go process them.
});
在调用evaluate之前,您应该将计算推送到队列中,并发送最旧的计算以进行评估。
if(computations.length > 0) {
computations.push(new_comp); // Push on your newest compuation
var comp = computations[0]; // Save oldest computation
computations.splice(0,1); // Remove oldest computation from array
evaluate(comp); // Evaluate oldest computation
}
else {
evaluate(new_comp); // Evaluate computation
}
evaluate(new_comp); // Evaluate oldest computation
你的"完成"在calculate.length === 0时,标志将会出现。而这只会自然地用上面的代码来处理。任何时候你在n.on中留下0个计算('消息',处理程序..你可以调用你的结果处理函数:
要处理结果,这是一个简单的for循环。
function process_results() {
if(results.length > 0)
for(x in results)
console.log("New result: "+x);
}
答案 2 :(得分:0)
这可能不是严格的“正确”,并且已经晚了6年以上,但似乎可以在2020年实现
> process.version
'v12.14.1'
> var ignore = process.on('custom',function(e){console.dir(e,{depth:null});})
undefined
> process.emit('custom',{e:"hello"})
{ e: 'hello' }
true
>
即,传递给process.emit(x,obj)
的任何对象都将发送到针对匹配的process.on(x,function(obj){ /* ... */ })
回调进行注册的对象
希望这会有所帮助。