首页 > 解决方案 > Nodejs流行为,未调用管道回调

问题描述

为什么管道从不调用它的回调?此外,变换函数在 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);
    }
);

标签: javascriptnode.jspipelinenode-streams

解决方案


在第 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 可以改变它的含义)。


推荐阅读