17

I currently have an operation in a module that is blocking, so I'm looking at making this into a child process that I fork instead.

If I want to do that, then I of course need to modify the architecture of my module. The module requires that a dependency is injected by calling the module as a function, passing in the dependency, like so:

var dependency = { name: "Bob" }
require('worker')(dependency)

Then in my worker module:

module.exports = function (dependency) {
  // Outputs { name: "Bob" }
  console.log(dependency)
}

How can I turn this example into a child process being forked?

3
  • fork a child and then send the dependency from the parent using child.send(message). The object you pass can't be cyclic. nodejs.org/api/… Commented Mar 12, 2013 at 17:59
  • @GabrielLlamas I need to use child.send(message) later to actually send data to the worker (not dependencies). I don't understand how my worker can differentiate between what sort of messages it is being sent, and how to handle them. Commented Mar 12, 2013 at 18:03
  • well, I was doing a complete example while you accepted another answer, look at it! Commented Mar 12, 2013 at 18:33

3 Answers 3

29

When using .fork() you are spinning up a completely separate process, so you are not able to pass around references between the parent and child processes (and are limited to messaging after the process has been created).

An approach not requiring messaging is to pass arguments (in an array) when you fork the process. Although I believe you'll have to stick with simple string/number values (but it looks like this might be enough for you from the code). Eg.:

At top level:

var name = 'bob'
var args = [name];
var childProcess = require('child_process').fork(__dirname + '/worker', args);

In the worker process:

var name = process.argv[2]; //AFIAK elements 0 and 1 are already populated with env info

Update

If you really want to go the messaging route (which I'd hesitate to recommend if you already need to send messages), then you could differentiate between the types of messages something like this (there may be more elegant ways):

At top level:

var childProcess = require('child_process').fork(__dirname + '/worker');
childProcess.send({msgtype:'dependencies', content:dependencies});

//Then to send 'normal' message:
childProcess.send({msgtype:'myothermessagetype', content:'some content'}

In worker process:

process.on('message', function(msg){
    if(msg.mtype == 'dependencies') {
       var dependencies = msg.content;
       //Do something with dependencies
    } else if(msg.mtype == 'myothermessagetype') {
       var normalmessage = msg.content;
       //Do something in response to normal message.
    }
});
Sign up to request clarification or add additional context in comments.

9 Comments

Thank you for the informative answer. Unfortunately I require an object to be passed… although I guess I could stringify it.
Yeah, personally I'd stringify or, if it's not too complex, hack it up into it's constituents temporarily. I don't like to complicate the messaging logic with both setup and normal 'runtime' stuff.
fails when doing "node a/b/c/app.js"
@UpTheCreek Would you do the latter or just stringify and send as arg?
@GabrielLlamas - could you give more detail pls? Do you mean the reference to worker.js? (that's just an example).
|
3

a.js

var fork = require ("child_process").fork;
var child;
var init = false;

var m = module.exports = {};
m.init = function (o){
    if (init) return;
    init = true;
    child = fork (__dirname + "/child");
    child.send ({ init: o });
};
m.print = function (o){
    if (!init) return;
    child.send ({ msg: o });
};
m.uninit = function (){
    if (!init) return;
    child.on ("exit", function (){
        init = false;
    });
    child.kill ();
};

child.js

var dependency;

var print = function (o){
    console.log (o + dependency.name);
};

process.on ("message", function (o){
    if (o.init){
        dependency = o.init;
    }else{
        print (o.msg);
    }
});

b.js

var a = require ("./a");
a.init ({ name: "asd" });
a.print ("hi, ");
setTimeout (function (){
    a.uninit ();
}, 1000);

Prints: hi, asd

Comments

1

In the main module:

var dependency = {message: 'hello there'};
var args = [JSON.stringify(dependency)];
var child = require('child_process').fork('worker', args);
child.send('sayhello');
child.send('exit');

And in the child process module (worker.js):

var dependency = JSON.parse(process.argv[2]);
process.on('message', function(m){
    if(m == 'sayhello') console.log(dependency.message);
    else if(m == 'exit') process.exit();
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.