Stream在node.js中是一个抽象的接口,基于EventEmitter,也是一种Buffer的高级封装,用来处理流数据。流模块便是提供各种API让我们可以很简单的使用Stream。
流分为四种类型,如下所示:
Readable,可读流
Writable,可写流
Duplex,读写流
Transform,扩展的Duplex,可修改写入的数据
1、Readable可读流
通过stream.Readable可创建一个可读流,它有两种模式:暂停和流动。
在流动模式下,将自动从下游系统读取数据并使用data事件输出;暂停模式下,必须显示调用
stream.read()方法读取数据,并触发data事件。所有的可读流最开始都是暂停模式,可以通过以下方法切换到流动模式:
监听’data’事件
调用
stream.resume()方法调用
stream.pipe()方法将数据输出到一个可写流Writable同样地,也可以切换到暂停模式,有两种方法:
如果没有设置pipe目标,调用
stream.pause()方法即可。如果设置了pipe目标,则需要移除所有的data监听和调用
stream.unpipe()方法在Readable对象中有一个
_readableSate的对象,通过该对象可以得知流当前处于什么模式,如下所示: readable._readableState.flowing = null,没有数据消费者,流不产生数据
readable._readableState.flowing = true,处于流动模式
readable._readableState.flowing = false,处于暂停模式
为什么使用流取数据
对于小文件,使用
fs.readFile()方法读取数据更方便,但需要读取大文件的时候,比如几G大小的文件,使用该方法将消耗大量的内存,甚至使程序崩溃。这种情况下,使用流来处理是更合适的,采用分段读取,便不会造成内存的’爆仓’问题。data事件
在stream提供数据块给消费者时触发,有可能是切换到流动模式的时候,也有可能是调用
readable.read()方法且有有效数据块的时候,使用如下所示:
const fs = require('fs');const rs = fs.createReadStream('./appbak.js');
var chunkArr = [],
chunkLen = 0;
rs.on('data',(chunk)=>{
chunkArr.push(chunk);
chunkLen+=chunk.length;
});
rs.on('end',(chunk)=>{
console.log(Buffer.concat(chunkArr,chunkLen).toString());
});
readable事件
当流中有可用数据能被读取时触发,分为两种,新的可用的数据和到达流的末尾,前者









