问题描述:

I got a main process and this fork a child. This child do some calculations. At some point of the code in the child I want to ask the parent for some data. This request is highly dynamic and at this point i want to wait for a answer/response of this request. But how do I wait for process.send() or is it possible to add a Callback function to .send()?

I tried to break down my Problem to a simple example.

The highly dynamic value is in my example the randomval in the worker.

And i know that the assignment

var c = process.send({msg:'get_c',randomval:Math.floor((Math.random()*10)+1)});

can't work. But i no other idea how to describe the Problem.

main.js

var childProcessCalc = require('child_process').fork(__dirname + '/worker');

childProcessCalc.send({msgtype:'docalc'});

childProcessCalc.on('message',function(msg){

if(msg.msg === 'pi')

{

console.log("Pi"+msg.pi+" by c="+msg.c);

}

else if(msg.msg === 'get_c')

{

console.log('child wants c');

childProcessCalc.send({msgtype:'your_c',c:1000000*msg.randomval});

}

});

childProcessCalc.on('exit',function(){

console.log('main:the childProzess has exit!')

});

worker.js

process.on('message', function(msg){

if(msg.msgtype == 'docalc') {

//Here is my Problem, how to wait for the message thats the response for

//exactly this send / randomval, or how to add a callback to send

var c = process.send({msg:'get_c',randomval:Math.floor((Math.random()*10)+1)});

var Pi=0;

var n=1;

for (var i=0;i<=c;i++)

{

Pi=Pi+(4/n)-(4/(n+2))

n=n+4

}

process.send({msg:'pi',pi:Pi,c:c})

}

else if(msg.msgtype === 'your_c')

{

console.log('parent hase sendc='+msg.c);

}

});

网友答案:

I have a solution to my problem and it works well for me, but because im very new at nodejs i still not now if this is the best way. Its feel like a overhead.

In a few words what i have done: I added a object that stores a random callback identifier with the callback function that has to be called if we got a response for the given callback identifier. When i now call send() from worker i send the identifier to the main process and the main process send this identifier back when he has finished. So i can lookup in my callback var (dynamicMassages ) for the callbackfnc to call and execute it.

main2.js

var childProcessCalc = require('child_process').fork(__dirname + '/worker2');
childProcessCalc.send({msgtype:'docalc'});

childProcessCalc.send({msgtype:'docalc'});

childProcessCalc.on('message',function(msg){
if(msg.msg === 'pi')
{
    console.log("Pi"+msg.pi+" by c="+msg.c);
}
else if(msg.msg === 'get_c')
{
    console.log('child wants c');
    childProcessCalc.send({msgtype:'your_c',callbackid:msg.callbackid, c:1000000*msg.randomval});
}
});

childProcessCalc.on('exit',function(){
    console.log('main:the childProzess has exit!')
});

worker2.js

var dynamicMassages = {};

process.on('message', function(msg){

var getRandomId = function(){
    var text = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    for( var i=0; i < 5; i++ )
    {
        text += possible.charAt(Math.floor(Math.random() * possible.length));
    }

    if(dynamicMassages[text] === undefined)
    {
        return text;
    }
    else
    {
        return getRandomId();
    }
};

if(msg.msgtype == 'docalc') {
    var randomId = getRandomId();
    var callbackFnc = function(c){
        var Pi=0;
        var n=1;
        for (var i=0;i<=c;i++)
        {
            Pi=Pi+(4/n)-(4/(n+2))
            n=n+4
        }
        console.log("callbackFnc For:"+randomId);
        process.send({msg:'pi',pi:Pi,c:c})
        delete dynamicMassages[randomId];
    };

    dynamicMassages[randomId] = callbackFnc;//callbackFnc;
    process.send({msg:'get_c',callbackid: randomId, randomval:Math.floor((Math.random()*10)+1)});


}
else if(msg.msgtype === 'your_c')
{
    console.log('parent hase sendc='+msg.c+' for callbackId '+msg.callbackid);
    if(msg.callbackid !== undefined)
    {
        dynamicMassages[msg.callbackid](msg.c);
    }
}

});

Please leave a comment if you would to it the same way.

网友答案:

I'd suggest that you go with a message bus, either a full-blown advanced solution such as RabbitMQ, or a little smaller solution, such as axon.

Basically, what you want to do is inter-process communication, and I'd try to stick to established protocols and standards as much as possible, and avoid rolling your very own solution. As RabbitMQ builds on top of AMQP, I guess you can call it standard.

相关阅读:
Top