简体   繁体   中英

Handling chunked responses from process.stdout 'data' event

I have some code which I can't seem to fix. It looks as follows:

var childProcess = require('child_process');
var spawn = childProcess.spawn;
child = spawn('./simulator',[]);

child.stdout.on('data',
    function(data){
        console.log(data);
    }
);

This is all at the backend of my web application which is running a specific type of simulation. The simulator executable is ac program which runs a loop waiting to be passed data (via its standard input) When the inputs come in for the simulation (ie from the client), I parse the input, and then write data to the child process stdin as follows:

child.stdin.write(INPUTS);

Now the data coming back is 40,000 bytes give or take. But the data seems to be getting broken into chunks of 8192 bytes. I've tried fixing the standard output buffer of the c program but it doesnt fix it. I'm wondering if there is a limit to the size of the 'data' event that is imposed by node.js? I need it to come back as one chunk.

If you are dealing with IO in a web application you really want to stick with the async methods. You need something like the following (untested). There is a good sample of how to consume the Stream API in the docs

var data = '';
child.stdout.on('data',
    function(chunk){
        data += chunk;
    }
);    

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

The buffer chunk sizes are applied in node. Nothing you do outside of node will solve the problem. There is no way to get what you want from node without a little extra work in your messaging protocol. Any message larger than the chunk size will be chunked. There are two ways you can handle this issue.

  1. If you know the total output size before you start to stream out of C, prepend the message length to the data so the node process knows how many chunks to pull before terminating the entire message.
  2. Determine a special character you can append to the message you are sending from the C program. When node sees that character, you end the input from that message.

I ran into the same problem. I tried many different things and was starting to get annoyed. I tried prepending and appending with special characters. Maybe I was stupid but I just couldn't get it right.

I ran into a module called linerstream which basically parses every chunk until it sees an EOF . You can use it like this:

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

The important part is that you do have to write data to stdout with a line that ends with EOF . Otherwise it doesn't know it is the end.

I can say this worked me. Hopefully it helps other people.

ppejovic's solution works, but I prefer concat-stream .

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

There are a number of good stream helpers worth looking into based on your problem area. Take a look at substack's stream-handbook .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM