[可写流]和[可读流]都会在内部的缓冲器中存储数据,可以分别使用的 writable.writableBuffer 或 readable.readableBuffer 来获取。
可缓冲的数据大小取决于传入流构造函数的 highWaterMark 选项。
对于普通的流,highWaterMark 指定了[字节的总数][hwm-gotcha]。
对于对象模式的流,highWaterMark 指定了对象的总数。
当调用 [stream.push(chunk)][stream-push] 时,数据会被缓冲在可读流中。
如果流的消费者没有调用 [stream.read()][stream-read],则数据会保留在内部队列中直到被消费。
一旦内部的可读缓冲的总大小达到 highWaterMark 指定的阈值时,流会暂时停止从底层资源读取数据,直到当前缓冲的数据被消费
(也就是说,流会停止调用内部的用于填充可读缓冲的 readable._read())。
当调用 [writable.write(chunk)][stream-write] 时,数据会被缓冲在可写流中。
当内部的可写缓冲的总大小小于 highWaterMark 设置的阈值时,调用 writable.write() 会返回 true。
一旦内部缓冲的大小达到或超过 highWaterMark 时,则会返回 false。
stream API 的主要目标,特别是 [stream.pipe()],是为了限制数据的缓冲到可接受的程度,也就是读写速度不一致的源头与目的地不会压垮内存。
The highWaterMark option is a threshold, not a limit: it dictates the amount
of data that a stream buffers before it stops asking for more data. It does not
enforce a strict memory limitation in general. Specific stream implementations
may choose to enforce stricter limits but doing so is optional.
因为 [Duplex] 和 [Transform] 都是可读又可写的,所以它们各自维护着两个相互独立的内部缓冲器用于读取和写入,
这使得它们在维护数据流时,读取和写入两边可以各自独立地运作。
例如,[net.Socket] 实例是 [Duplex] 流,它的可读端可以消费从 socket 接收的数据,而可写端则可以将数据写入到 socket。
因为数据写入到 socket 的速度可能比接收数据的速度快或者慢,所以读写两端应该独立地进行操作(或缓冲)。
