Node.js 在nodejs中将数据从子节点管道化到父节点
我有一个nodejs父进程,它启动另一个nodejs子进程。子进程执行一些逻辑,然后将输出返回给父进程。输出很大,我正在尝试使用管道进行通信,正如child.send()方法文档中所建议的那样(顺便说一句,该方法工作得很好) 我想有人建议如何正确建立这种沟通渠道。我希望能够将数据从父级发送到子级,也希望能够将数据从子级发送到父级。我已经开始了一点,但它是不完整的(只发送消息从家长到孩子),并抛出一个错误 父文件代码:Node.js 在nodejs中将数据从子节点管道化到父节点,node.js,pipe,child-process,Node.js,Pipe,Child Process,我有一个nodejs父进程,它启动另一个nodejs子进程。子进程执行一些逻辑,然后将输出返回给父进程。输出很大,我正在尝试使用管道进行通信,正如child.send()方法文档中所建议的那样(顺便说一句,该方法工作得很好) 我想有人建议如何正确建立这种沟通渠道。我希望能够将数据从父级发送到子级,也希望能够将数据从子级发送到父级。我已经开始了一点,但它是不完整的(只发送消息从家长到孩子),并抛出一个错误 父文件代码: var child_process = require('child_proc
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());
})
上述代码打印预期输出(“测试2”)以及以下错误:
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.');
您的代码可以工作,但通过使用Streamizer包从字符串创建读取流,传输该字符串后,您的通信通道将自动关闭,这就是您收到ENOTCONN错误的原因
能够在流中发送多个消息,考虑使用<代码>。您可以随时调用此选项:
child.stdio[3].write('First message.\n');
child.stdio[3].write('Second message.\n');
如果您想使用此方法发送多个离散消息(根据您之前使用child.send()
的评论,我认为是这种情况),最好使用一些分隔符,以便在子对象中读取流时能够拆分消息。在上面的例子中,我使用了换行符。帮助进行此拆分的一个有用包是
现在,为了从父级中的子级创建另一个通信通道,只需向stdio添加另一个“管道”
您可以在child中写入:
fs.createWriteStream(null, {fd: 4}).write('Sending a message back.');
并在家长中阅读:
child.stdio[4].pipe(process.stdout);
这将向控制台打印“发送回消息”。您可以使用
fork()执行此操作。
我刚刚为自己解决了这个问题…fork()
是spawn的更高版本,一般建议使用fork()
而不是spawn()
如果使用{silent:true}
选项,stdio将通过管道传输到父进程
const cp = require('child_process');
const n = cp.fork(<path>, args, {
cwd: path.resolve(__dirname),
detached: 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.once('exit', function (err) {
console.error(err.stack);
ee.emit('exit', err);
});
const cp=require('child_process');
常量n=cp.fork(,args{
cwd:path.resolve(_dirname),
是的,
});
n、 stdout.setEncoding('utf8');
//在这里,我们可以监听来自子进程的数据流:
n、 stdout.on('data',(data)=>{
ee.emit(“数据”,数据);
});
//您还可以侦听子进程发出的其他事件
n、 on('error',函数(err){
控制台错误(错误堆栈);
ee.emit('error',err);
});
n、 on('message',函数(msg){
ee.emit('message',msg);
});
n、 on('uncaughtException',函数(err){
控制台错误(错误堆栈);
ee.emit('error',err);
});
n、 一次(“退出”,功能(错误){
控制台错误(错误堆栈);
ee.emit('exit',err);
});
我遇到了相同的问题,并使用{end:false}选项修复了错误。不幸的是,只有在处理少量数据的离散写入时,公认的答案才有效。如果您有大量数据(而不仅仅是短消息),则需要处理流控制,并且使用.write()不是最好的方法。对于这样的场景(大型数据传输),最好像最初在代码中那样使用.pipe()函数来处理流控制
引发错误的原因是父进程中的可读流正试图结束并关闭子进程的可写流输入管道。您应该在父进程管道中使用{end:false}
选项:
原始代码:
require('streamizer').createReadStream('test 2').pipe(child.stdio[3]);
建议的修改:
require('streamizer').createReadStream('test 2').pipe(child.stdio[3],{end:false});
请参阅NodeJs文档中的详细信息:
希望这能帮助其他人解决此问题。请将它引发的错误包括在内。谢谢您的输入。然而,我希望能够在两个方向上进行沟通,甚至可能多次。我更喜欢使用stdout/stderr来处理其他类型的数据,这就是我在那里使用“管道”的原因。我完全重写了我的答案,以便更好地符合您提出的问题。让我知道这是否回答了您的问题:)。再次感谢您的输入。这帮我解决了我的问题!谢谢你的意见。我稍后会测试它,如果它有效,我会将您的答案标记为已接受!