浅谈Node.js:理解stream

2020-06-17 07:07:32易采站长站整理
stream.read()
方法返回可用数据,后者返回null,如下所示:


const rs = fs.createReadStream('./appbak.js');
var chunkArr = [],
chunkLen = 0;

rs.on('readable',()=>{
var chunk = null;
//这里需要判断是否到了流的末尾
if((chunk = rs.read()) !== null){
chunkArr.push(chunk);
chunkLen+=chunk.length;
}
});
rs.on('end',(chunk)=>{
console.log(Buffer.concat(chunkArr,chunkLen).toString());
});

pause和resume方法

stream.pause()
方法让流进入暂停模式,并停止’data’事件触发,
stream.resume()
方法使流进入流动模式,并恢复’data’事件触发,也可以用来消费所有数据,如下所示:


const rs = fs.createReadStream('./下载.png');
rs.on('data',(chunk)=>{
console.log(`接收到${chunk.length}字节数据...`);
rs.pause();
console.log(`数据接收将暂停1.5秒.`);
setTimeout(()=>{
rs.resume();
},1000);
});
rs.on('end',(chunk)=>{
console.log(`数据接收完毕`);
});

pipe(destination[, options])方法

pipe()
方法绑定一个可写流到可读流上,并自动切换到流动模式,将所有数据输出到可写流,以及做好了数据流的管理,不会发生数据丢失的问题,使用如下所示:


const rs = fs.createReadStream('./app.js');
rs.pipe(process.stdout);

以上介绍了多种可读流的数据消费的方法,但对于一个可读流,最好只选择其中的一种,推荐使用

pipe()
方法。

2、Writable可写流

所有的可写流都是基于

stream.Writable
类创建的,创建之后便可将数据写入该流中。

write(chunk[, encoding][, callback])方法

write()
方法向可写流中写入数据,参数含义:

chunk,字符串或buffer
encoding,若chunk为字符串,则是chunk的编码
callback,当前chunk数据写入磁盘时的回调函数

该方法的返回值为布尔值,如果为false,则表示需要写入的数据块被缓存并且此时缓存的大小超出highWaterMark阀值,否则为true。

 使用如下所示:


const ws = fs.createWriteStream('./test.txt');
ws.write('nihao','utf8',()=>{process.stdout.write('this chunk is flushed.');});
ws.end('done.')

背压机制

如果可写流的写入速度跟不上可读流的读取速度,write方法添加的数据将被缓存,逐渐增多,导致占用大量内存。我们希望的是消耗一个数据,再去读取一个数据,这样内存就维持在一个水平上。如何做到这一点?可以利用write方法的返回值来判断可写流的缓存状态和’drain’事件,及时切换可读流的模式,如下所示: