缓冲
Writable
和 Readable
流都将数据存储在内部缓冲区中。
可能缓冲的数据量取决于传给流的构造函数的 highWaterMark
选项。
对于普通的流,highWaterMark
选项指定字节的总数。
对于在对象模式下操作的流,highWaterMark
指定对象的总数。
当实现调用 stream.push(chunk)
时,数据缓存在 Readable
流中。
如果流的消费者没有调用 stream.read()
,则数据会一直驻留在内部队列中,直到被消费。
一旦内部读取缓冲区的总大小达到 highWaterMark
指定的阈值,则流将暂时停止从底层资源读取数据,直到可以消费当前缓冲的数据(也就是,流将停止调用内部的用于填充读取缓冲区 readable._read()
方法)。
当重复调用 writable.write(chunk)
方法时,数据会缓存在 Writable
流中。
虽然内部的写入缓冲区的总大小低于 highWaterMark
设置的阈值,但对 writable.write()
的调用将返回 true
。
一旦内部缓冲区的大小达到或超过 highWaterMark
,则将返回 false
。
stream
API 的一个关键目标,尤其是 stream.pipe()
方法,是将数据缓冲限制在可接受的水平,以便不同速度的来源和目标不会压倒可用内存。
highWaterMark
选项是阈值,而不是限制:它规定了流在停止请求更多数据之前缓冲的数据量。
它通常不强制执行严格的内存限制。
特定的流实现可能会选择实施更严格的限制,但这样做是可选的。
由于 Duplex
和 Transform
流都是 Readable
和 Writable
,因此每个流都维护两个独立的内部缓冲区,用于读取和写入,允许每一端独立操作,同时保持适当且高效的数据流。
例如,net.Socket
实例是 Duplex
流,其 Readable
端允许消费从套接字接收的数据,其 Writable
端允许将数据写入套接字。
因为数据可能以比接收数据更快或更慢的速度写入套接字,所以每一端都应该独立于另一端进行操作(和缓冲)。
内部缓冲的机制是内部的实现细节,可能随时更改。
但是,对于某些高级实现,可以使用 writable.writableBuffer
或 readable.readableBuffer
检索内部的缓冲区。
不鼓励使用这些未记录的属性。
Both Writable
and Readable
streams will store data in an internal
buffer.
The amount of data potentially buffered depends on the highWaterMark
option
passed into the stream's constructor. For normal streams, the highWaterMark
option specifies a total number of bytes. For streams operating
in object mode, the highWaterMark
specifies a total number of objects.
Data is buffered in Readable
streams when the implementation calls
stream.push(chunk)
. If the consumer of the Stream does not
call stream.read()
, the data will sit in the internal
queue until it is consumed.
Once the total size of the internal read buffer reaches the threshold specified
by highWaterMark
, the stream will temporarily stop reading data from the
underlying resource until the data currently buffered can be consumed (that is,
the stream will stop calling the internal readable._read()
method that is
used to fill the read buffer).
Data is buffered in Writable
streams when the
writable.write(chunk)
method is called repeatedly. While the
total size of the internal write buffer is below the threshold set by
highWaterMark
, calls to writable.write()
will return true
. Once
the size of the internal buffer reaches or exceeds the highWaterMark
, false
will be returned.
A key goal of the stream
API, particularly the stream.pipe()
method,
is to limit the buffering of data to acceptable levels such that sources and
destinations of differing speeds will not overwhelm the available memory.
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.
Because Duplex
and Transform
streams are both Readable
and
Writable
, each maintains two separate internal buffers used for reading and
writing, allowing each side to operate independently of the other while
maintaining an appropriate and efficient flow of data. For example,
net.Socket
instances are Duplex
streams whose Readable
side allows
consumption of data received from the socket and whose Writable
side allows
writing data to the socket. Because data may be written to the socket at a
faster or slower rate than data is received, each side should
operate (and buffer) independently of the other.
The mechanics of the internal buffering are an internal implementation detail
and may be changed at any time. However, for certain advanced implementations,
the internal buffers can be retrieved using writable.writableBuffer
or
readable.readableBuffer
. Use of these undocumented properties is discouraged.