如下,读取一个文件,把file.js全部读取到内存,当file.js文件很小的时候并没有什么问题
const fs = require('fs'); fs.readFile('./file.js', (err, data) => { });
但是当file.js有几G、几十G或更大的时候,把整个文件读取到内存显然就会出现内存不够用的问题。
可不可以每次读取固定长度的数据到缓冲区,处理完缓冲区后再继续读取?这就是流。
Node.js的Stream模块提供了四种类型的流:
Readable Streams (可读流) Writable Streams (可写流) Duplex Streams (双工流) Transform Streams (转换流)
可读流处于2种模式之一:Flowing Mode和Paused Mode
绑定 data 会自动触发Flowing Mode,第一次 data 事件会在下一个 tick 中触发。
从系统底层读取数据并push()到缓存池,达到highWaterMark后 push() 返回 false,资源停止流向缓存池,并触发data事件消费数据。
切换到Flowing模式的方法:
监听data事件 调用stream.resume()方法 调用stream.pipe()方法将数据发送到 Writable
Stream 默认是Paused模式,必须显式调用stream.read()方法来从流中读取数据。每一次数据达到缓存池都会触发一次 readable 事件,也就是每一次 push() 都会触发 readable。
切换到Paused模式的方法:
监听readable事件 如果不存在管道目标(pipe destination),调用 stream.pause() 如果存在管道目标,取消 data 事件监听,并调用 stream.unpipe() 方法移除所有管道
write() 的数据会进入队列池,如果达到highWaterMark,则会返回 false,否则返回 true,返回 false 后仍然可以继续 write(),数据会缓存在内存中不会丢失,write() 会继续返回 false。
write() 返回 false 后, 最好等drain事件触发后再继续写入。
Duplex 是同时实现了 Readable 和 Writable,但输出与输入没有关系。
Tranform 继承自 Duplex,但在 Transform 中 Writable 写入的数据经变换后会自动添加到 Readable。