问题
I'm spawning a child that produces lots of data (I'm using 'ls -lR /' here as an example). I want to asynchronously read the child's stdout 100 bytes at a time.
So I want to do: get100().then(process100).then(get100).then(process100).then(...
For some reason, this code only loops 3 times and I stop getting Readable events. I can't figure out why?
var Promise = require('bluebird');
var spawn = require("child_process").spawn;
var exec = spawn( "ls", [ "-lR", "/"] );
var get100 = function () {
return new Promise(function(resolve, reject) {
var tryTransfer = function() {
var block = exec.stdout.read(100);
if (block) {
console.log("Got 100 Bytes");
exec.stdout.removeAllListeners('readable');
resolve();
} else console.log("Read Failed - not enough bytes?");
};
exec.stdout.on('readable', tryTransfer);
});
};
var forEver = Promise.method(function(action) {
return action().then(forEver.bind(null, action));
});
forEver(
function() { return get100(); }
)
回答1:
Using event-stream, you can emit 100 bytes data from the spawned process as long as there is data to read (streams are async):
var es = require('event-stream');
var spawn = require("child_process").spawn;
var exec = spawn("ls", ["-lR", "/"]);
var stream = es.readable(function (count, next) {
// read 100 bytes
while (block = exec.stdout.read(100)) {
// if you have tons of data, it's not a good idea to log here
// console.log("Got 100 Bytes");
// emit the block
this.emit('data', block.toString()); // block is a buffer (bytes array), you may need toString() or not
}
// no more data left to read
this.emit('end');
next();
}).on('data', function(data) {
// data is the 100 bytes block, do what you want here
// the stream is pausable and resumable at will
stream.pause();
doStuff(data, function() {
stream.resume();
});
});
来源:https://stackoverflow.com/questions/34971616/node-js-reading-child-process-stdout-100-bytes-at-a-time