问题描述
为什么管道从不调用它的回调? 此外,转换函数在 16 个块后停止调用。
例如:
const { Readable,Transform,pipeline } = require('stream');
const readable = new Readable({
objectMode: true,read() {
this.push(count++);
if (count > 20) {
this.push(null);
}
}
});
const transform = new Transform({
objectMode: true,transform(chunk,encoding,callback) {
data.push(chunk);
console.log('transform - chunk: ',chunk.toString());
callback(null,chunk);
}
});
let count = 1,data = [];
pipeline(
readable,transform,(error) => {
if (error) console.log('pipeline callback - ERROR: ',error);
else console.log('pipeline callback - data: ',data);
}
);
解决方法
在第 16 次调用之后不再调用转换函数是一个提示。 原因如下: https://nodejs.org/api/stream.html#stream_new_stream_writable_options
在 objectMode 中,转换的默认 highWaterMark 为 16。因为转换函数还通过回调将数据“推送”到它自己的可读数据,这导致可读缓冲区变满(因为没有进一步的可写来消耗可读数据)。 因此,流由于背压而暂停,背压从流的转换可读部分开始,“流”到转换可写端,然后到达最终暂停的原始可读流。
- 转换可读 - 推送 16 个块后暂停
- transform-writable - 不断接受数据块并缓冲到上游可读的下 16 个数据块
- 可读 - 一直读到它的缓冲区已满,接下来的 16 个块,然后暂停
所以原始可读将在 16 * 3 块或 48 次读取后默认暂停。
当不在 objectMode 中时,缓冲区/字符串的 highWaterMark 是 16384 字节(尽管 setEncoding 可以改变它的含义)。