在nodejs中将数据从子节点传递给父节点

我有一个nodejs父进程,启动另一个nodejssubprocess。 subprocess执行一些逻辑,然后将输出返回给父进程。 输出很大,我试图使用pipe道进行通信,正如在child.send()方法(它工作正常BTW)的文档中所build议的。

我希望有人build议如何正确build立这个沟通渠道。 我希望能够从父母发送数据到孩子,也能够发送数据从孩子到父母。 我已经开始了一些,但它是不完整的(只发送消息从父母到孩子),并引发错误。

父文件代码:

var child_process = require('child_process'); var opts = { stdio: [process.stdin, process.stdout, process.stderr, 'pipe'] }; var child = child_process.spawn('node', ['./b.js'], opts); require('streamifier').createReadStream('test 2').pipe(child.stdio[3]); 

子文件代码:

 var fs = require('fs'); // read from it var readable = fs.createReadStream(null, {fd: 3}); var chunks = []; readable.on('data', function(chunk) { chunks.push(chunk); }); readable.on('end', function() { console.log(chunks.join().toString()); }) 

上面的代码打印预期的输出(“testing2”)以及以下错误:

 events.js:85 throw er; // Unhandled 'error' event ^ Error: shutdown ENOTCONN at exports._errnoException (util.js:746:11) at Socket.onSocketFinish (net.js:232:26) at Socket.emit (events.js:129:20) at finishMaybe (_stream_writable.js:484:14) at afterWrite (_stream_writable.js:362:3) at _stream_writable.js:349:9 at process._tickCallback (node.js:355:11) at Function.Module.runMain (module.js:503:11) at startup (node.js:129:16) at node.js:814:3 

最佳答案:

父母的代码:

 var child_process = require('child_process'); var opts = { stdio: [process.stdin, process.stdout, process.stderr, 'pipe', 'pipe'] }; var child = child_process.spawn('node', ['./b.js'], opts); child.stdio[3].write('First message.\n', 'utf8', function() { child.stdio[3].write('Second message.\n', 'utf8', function() { }); }); child.stdio[4].pipe(process.stdout); 

孩子的代码:

 var fs = require('fs'); // read from it var readable = fs.createReadStream(null, {fd: 3}); readable.pipe(process.stdout); fs.createWriteStream(null, {fd: 4}).write('Sending a message back.'); 

你的代码工作正常,但是通过使用stream化器包创build一个string读取stream,你的通信通道会在这个string被传送后自动closures,这就是你得到一个ENOTCONN错误的原因。

为了能够通过stream发送多个消息,请考虑在其上使用.write 。 您可以随时拨打电话:

 child.stdio[3].write('First message.\n'); child.stdio[3].write('Second message.\n'); 

如果你想使用这种方法发送多个离散消息(我相信这是基于你之前使用child.send()说法),最好使用一些分隔符来分割消息在小孩读取stream。 在上面的例子中,我使用了换行符。 事件stream是一个有用的帮助分裂的软件包。

现在,为了从父母的孩子创build另一个沟通渠道,只需添加另一个“pipe道”您的stdio。

你可以写在小孩身上:

 fs.createWriteStream(null, {fd: 4}).write('Sending a message back.'); 

并从父母那里读取它:

 child.stdio[4].pipe(process.stdout); 

这将打印“发送消息”。 到控制台。

我遇到了同样的问题,并使用{end:false}选项来修复错误。 不幸的是,接受的答案只在处理短数据量的离散写入时才起作用。 如果你有很多的数据(而不是简单的消息),你需要处理stream量控制,使用.write()不是最好的。 对于这样的情况(大数据传输),最好使用你的代码中最初使用的.pipe()函数来处理stream量控制。

由于父进程中的可读stream尝试结束并closuressubprocess的可写入streaminputpipe道,因此会引发该错误。 您应该在父进程pipe道中使用{end: false}选项:

原始代码: require('streamifier').createReadStream('test 2').pipe(child.stdio[3]);

build议修改: require('streamifier').createReadStream('test 2').pipe(child.stdio[3], {end:false});

在NodeJs文档中查看详细信息: https ://nodejs.org/dist/latest-v5.x/docs/api/stream.html#stream_readable_pipe_destination_options

希望这可以帮助别人面对这个问题。

你可以用fork()来做到这一点

我只是为自己解决了这个问题… fork()是spawn的更高版本,build议一般使用fork()而不是spawn()

如果使用{silent:true}选项,stdio将被传送到父进程

  var cp = require('child_process'); var n = cp.fork(runnerPath, args, { cwd: path.resolve(__dirname), detached: true, silent: true }); n.stdout.setEncoding('utf8'); // here we can listen to the stream of data coming from the child process: n.stdout.on('data', (data) => { ee.emit('data',data); }); //you can also listen to other events emitted by the child process n.on('error', function (err) { console.error(err.stack); ee.emit('error', err); }); n.on('message', function (msg) { ee.emit('message', msg); }); n.on('uncaughtException', function (err) { console.error(err.stack); ee.emit('error', err); }); n.on('exit', function (err) { console.error(err.stack); ee.emit('exit', err); });