Nodejs 流行为,未调用管道回调

Nodejs stream behaviour, pipeline callback not called

为什么管道从不调用它的回调? 此外,转换功能在 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。因为转换函数也将数据“推送”到它自己的可读通过回调,这导致可读缓冲区变满(因为没有进一步的可写来使用可读数据)。 因此,流由于背压而暂停,背压从流的转换可读部分开始,“流动”到转换可写端,然后流到最终暂停的原始可读流。

  • transform-readable - 在推送 16 个块后暂停
  • transform-writable - 不断接受块并缓冲到上游可读的下一个 16 个块
  • 可读 - 一直读取直到其缓冲区已满,接下来的 16 个块,然后暂停

因此原始可读将默认在 16 * 3 个块或 48 次读取后暂停。

当不在objectMode时,buffer/string的highWaterMark是16384字节(虽然setEncoding可以改变这个的意思).