有一次我认为你可以告诉Node.js子进程按换行符来分块数据。如下所示,来自子进程的stderr数据事件将触发字符和单词,而不是行。理想情况下,我可以传递一个标志来告诉流只在一行数据就绪时触发数据事件。难道没有办法做到这一点吗?
我有这个:
const sh = spawn('sh', [ b ], {
cwd: cwd,
});
sh.stdout.pipe(fs.createWriteStream('/dev/null'));
var stderr = '';
var line = '';
sh.stderr.setEncoding('utf8');
sh.stderr.on('data', function (d) {
//trying to split by newlines, but this is hairy logic
const lines = String(d).split('\n');
line += lines.shift();
if(lines.length > 0){
if (!String(d).match(/npm/ig) && !String(d).match(/npm/ig)) {
stderr += d;
process.stderr.write.apply(process.stderr, arguments);
}
}
});
并且此处理程序中的数据不是整行
sh.stderr.on('data', function (d) {
// d is chunks of data but not whole lines
});
没有办法告诉stderr在触发'数据之前等待换行符。事件
答案 0 :(得分:5)
您可以使用Transform stream。
实施并非如此简单,因此我建议使用像split2这样的库。
这是基本的想法:
const Transform = require('stream').Transform;
const StringDecoder = require('string_decoder').StringDecoder;
const decoder = new StringDecoder('utf8');
const myTransform = new Transform({
transform(chunk, encoding, cb) {
if ( this._last === undefined ) { this._last = "" }
this._last += decoder.write(chunk);
var list = this._last.split(/\n/);
this._last = list.pop();
for (var i = 0; i < list.length; i++) {
this.push( list[i] );
}
cb();
},
flush(cb) {
this._last += decoder.end()
if (this._last) { push(this, this._last) }
cb()
}
});
sh.stderr.pipe( myTransform )
.on('data', function (line) {
console.log("[" + line + "]");
});