Sending an error object from a spawned child process via an IPC channel

I have enabled communication between parent and child processes to send JSON as follows:

Child:

try {  
  var price1 = parseInt(process.argv[2]);
  if (!price1) {
     throw new Error('Price in calculations.js undefined');
  }
  var result = {
    'timeStamp' : Date(),
    'prices' : { 'player1' : price1, 'player2' : 666}
  };
  process.send(result);
} catch (e) {
  // In case of an error, I get here as expected.
  process.send(e);
}

Parent:

var spawn = require('child_process').spawn;
var child = spawn('node', ['calculations.js', 333],  {stdio: [null,null,'pipe','ipc']});
child.on('message', function(data) {    
  if (data instanceof Error) {
    // In case of an error, this is never reached.
  } else {
    // do sthing with JSON object.
  }
});

JSON works great. But if I make a mistake, this will not work. I want to send the entire error object (with message and stack trace) from child to parent. But this is not like the error I am posting.

+4
source share
2 answers

Processes do not exchange memory, so the only way to communicate is with strings, objects are serialized by JSON when sending, and JSON when receiving. Objects with an error are not serialized by default:

JSON.stringify(new Error())
"{}"

, JSON- , instanceof .

:

Error.prototype.toJSON = function() {
    var ret = {
        name: this.name,
        message: this.message,
        stack: this.stack,
        __error__: true
    };
    // Add any custom properties such as .code in file-system errors
    Object.keys(this).forEach(function(key) {
        if (!ret[key]) {
            ret[key] = this[key];
        }
    }, this);
    return ret;
};

:

 JSON.stringify(new Error())

"{"name":"Error","message":"","stack":"Error\n    at <anonymous>:2:16\n    at Object.InjectedScript._evaluateOn (<anonymous>:762:137)\n    at Object.InjectedScript._evaluateAndWrap (<anonymous>:695:34)\n    at Object.InjectedScript.evaluate (<anonymous>:609:21)","__error__":true}"

:

function getMessageReceiver(fn) {
    return function(data) {
        var result = data;
        if (data && data.__error__) {
            result = new Error();
            result.message = data.message;
            result.stack = data.stack;
            result.name = data.name;
            Object.keys(data).forEach(function(key) {
                if (!result[key]) {
                    result[key] = data[key];
                }
            });
        }
        return fn.call(this, result);
    }
}

:

child.on('message', getMessageReceiver(function(data) {    
  if (data instanceof Error) {
    console.log(data.stack); // Stack is from child process
  } else {
    // do sthing with JSON object.
  }
}));
+2

, ,

var Error=function(mes){
    this.message=mes;
};

try {  
  var price1 = parseInt(process.argv[4]);
 if (!price1) {
     throw new Error('Price in calculations.js undefined');
 }
  var result = {
    'timeStamp' : Date(),
    'prices' : { 'player1' : price1, 'player2' : 666}
  };  console.log("inside try");
  process.send(result);
} catch (e) {
  // In case of an error, I get here as expected.
  console.log("inside catch");
  process.send(e);
}

Error , , instanceof Error.

var child = require('child_process').fork(__dirname + '/SO2.js', [333],  {stdio: [null,null,'pipe','ipc']});

child.on('message', function(data) {
  if(data.timeStamp){
    console.log("result received ");
  } 
  else{
    // do sthing with JSON object.
    console.log("user defined error messege"+data.message + JSON.stringify(data));
  }
});
+1

Source: https://habr.com/ru/post/1570132/


All Articles