How to pass function/callback to child process in Node.js?
Asked Answered
N

1

11

Let's say I have a parent.js containing a method named parent

var childProcess = require('child_process');

var options = {
    someData: {a:1, b:2, c:3},
    asyncFn: function (data, callback) { /*do other async stuff here*/ }
};

function Parent(options, callback) {
    var child = childProcess.fork('./child');
    child.send({
        method: method,
        options: options
    });
    child.on('message', function(data){
        callback(data,err, data,result);
        child.kill();
    });
}

Meanwhile in child.js

process.on('message', function(data){
    var method = data.method;
    var options = data.options;
    var someData = options.someData;
    var asyncFn = options.asyncFn; // asyncFn is undefined at here
    asyncFn(someData, function(err, result){
        process.send({
            err: err,
            result: result
        });
    });
});

I was wondering if passing functions to child process is not allowed in Node.js.

Why would asyncFn become undefined after it is sent to the child?

Is it related to JSON.stringify?

Nitrochloroform answered 20/1, 2015 at 4:11 Comment(0)
S
11

JSON doesn't support serializing functions (at least out of the box). You could convert the function to its string representation first (via asyncFn.toString()) and then re-create the function again in the child process. The problem though is you lose scope and context with this process, so your function really has to be standalone.

Complete example:

parent.js:

var childProcess = require('child_process');

var options = {
  someData: {a:1, b:2, c:3},
  asyncFn: function (data, callback) { /*do other async stuff here*/ }
};
options.asyncFn = options.asyncFn.toString();

function Parent(options, callback) {
  var child = childProcess.fork('./child');
  child.send({
    method: method,
    options: options
  });
  child.on('message', function(data){
    callback(data,err, data,result);
    child.kill();
  });
}

child.js:

process.on('message', function(data){
  var method = data.method;
  var options = data.options;
  var someData = options.someData;
  var asyncFn = new Function('return ' + options.asyncFn)();
  asyncFn(someData, function(err, result){
    process.send({
      err: err,
      result: result
    });
  });
});
Sellers answered 20/1, 2015 at 4:43 Comment(3)
Aww, beat me to it :PAverage
is new Function('return ' + funcString)(); safe for untrusted code?Center
@Center No, you'd need to instead use the vm module in a child process with the appropriate OS-level protections in place to be safe with "untrusted code."Sellers

© 2022 - 2024 — McMap. All rights reserved.