处理来自 process.stdout "data" 事件的分块响应



我有一些代码似乎无法修复。它看起来如下:

var childProcess = require('child_process');
var spawn = childProcess.spawn;
child = spawn('./simulator',[]);
child.stdout.on('data',
    function(data){
        console.log(data);
    }
);

这一切都在我的web应用程序的后端,该应用程序正在运行特定类型的模拟。模拟器可执行文件是一个c程序,它运行一个循环,等待传递数据(通过其标准输入)。当模拟输入(即来自客户端)时,我解析输入,然后将数据写入子进程stdin,如下所示:

child.stdin.write(INPUTS);

现在返回的数据是40000字节。但数据似乎被分解成8192个字节的块。我试过修复c程序的标准输出缓冲区,但它没有修复。我想知道node.js对"data"事件的大小是否有限制?我需要它作为一块回来。

缓冲区块大小应用于节点中。您在节点之外所做的任何事情都无法解决问题。若不在消息传递协议中做一些额外的工作,就无法从节点获得您想要的内容。任何大于块大小的消息都将被分块。有两种方法可以处理这个问题。

  1. 如果在开始从C中流出之前就知道了总输出大小,那么在数据中预先设置消息长度,这样节点进程就知道在终止整个消息之前要提取多少块
  2. 确定一个可以附加到从C程序发送的消息中的特殊字符。当节点看到该字符时,您将结束该消息的输入

如果您在web应用程序中处理IO,那么您确实希望使用异步方法。你需要以下内容(未经测试)。文档中有一个很好的示例,说明如何使用Stream API

var data = '';
child.stdout.on('data',
    function(chunk){
        data += chunk;
    }
);    
child.stdout.on('end',
    function(){
        // do something with var data
    }
);

我遇到了同样的问题。我尝试了很多不同的事情,开始感到恼火。我试着在前面加上一些特殊的字符。也许我很愚蠢,但我就是做不好。

我遇到了一个名为linerstream的模块,它基本上解析每个块,直到它看到一个EOF。你可以这样使用它:

process.stdout.pipe(new Linerstream()).on('data', (data) => {
    // data here is complete and not chunked 
});

重要的是,您必须使用以EOF结尾的行将数据写入stdout。否则,它不知道这就是结局。

我可以说这对我很有效。希望它能帮助其他人。

ppejovic的解决方案有效,但我更喜欢concat流。

var concat = require('concat-stream');
child.stdout.pipe(concat(function(data) {
    // all your data ready to be used.
});

根据您的问题领域,有许多好的流帮助程序值得研究。看看substack的流手册。

最新更新