Node中的Stream看这篇就够了

·  阅读 456

Node.js Stream(流)

Stream 是一个抽象接口,Node 中有很多对象实现了这个接口。例如,对http 服务器发起请求的request 对象就是一个 Stream,还有stdout(标准输出)。 下面我们通过可读流(fs.createReadStream),来了解一下流到底是怎么回事。

先看一下流的类型和常用的事件:

Node.js,Stream 有四种流类型:

  • Readable - 可读操作。
  • Writable - 可写操作。
  • Duplex - 可读可写操作.
  • Transform - 操作被写入数据,然后读出结果。

所有的 Stream 对象都是 EventEmitter 的实例。常用的事件有:

  • data - 当有数据可读时触发。
  • end - 没有更多的数据可读时触发。
  • error - 在接收和写入过程中发生错误时触发。
  • close - 关闭当前流并释放与之关联的所有资源(如套接字和文件句柄)。不直接调 用此方法,而应确保流得以正确释放。

看完上述是否觉得很枯燥,没关系下面让小白给大家讲个故事,看看可读流的使用到底怎么回事:

小白:皮皮虾每天上班必经过京承收费站,今天也不例外严重堵车了,更加倒霉的是:

收费站管理员:今天由于发生了一起很大交通事故,每通过一量车,收费站需要暂时关闭,5分钟之后再开启,下一辆车再过去。(highWaterMark:1,每次过一辆车)

皮皮虾:oh my god!上帝啊,我要迟到了,这是件很严重的事情(因为我这个月已经迟到6次了,额,多么吉利的数字啊,好吧,我闭嘴......)

小白:这时候,等啊等,等啊等,终于前边还有两辆车,就轮到皮皮虾了,收费站管理员开启了开关,一辆车过去了开关关闭了,等了5分钟之后,管理员打开了开关,第二辆车过去了,开关关闭了。

  
  rs.on('data',function (data) {
    console.log(data);
    rs.pause(); 
  });
  setTimeout(()=>{rs.resume()},50000) 
  

收费站管理员:恩,等五分钟再把开关,打开,我先玩会吃鸡的游戏。

小白:这下好了,游戏玩起来,一发不可收拾,居然忘记了打开开关,最终悲剧发生了,皮皮虾一天没上班,一天都在路上了,(也导致了end事件和close事件没有执行)当然,玩游戏的收费站大叔也由于被投诉,而遭到公司的开除。

好了故事讲完了,接下来看一下完整的代码,是不是更容易理解了呢?

可读流的小例子:


let fs = require('fs');
let rs = fs.createReadStream('./context.txt', {
  highWaterMark: 1, 
  flags:'r',
  autoClose:true, 
  start:0,
  end:3,
  encoding:'utf8'
});
rs.on('error',function (err) {
  console.log(err)
});
rs.on('open',function () {
  console.log('文件打开了');
});
rs.on('data',function (data) {
  console.log(data);
  rs.pause(); 
});
setTimeout(()=>{rs.resume()},50000) 
rs.on('end',function () {
  console.log('读取完毕了');
});
rs.on('close',function () {
  console.log('关闭')
});

以上代码的运行结果为:


文件打开了
1
2

总结:


1, context.txt文件的内容:123456789;
2, highWaterMark: 1, 读取1个字节,默认64k;
3, encoding:'utf8', encoding 读取默认都是buffer;
4, autoClose:true, 默认读取完毕后自动关闭;
5, 流是闭合区间 包start也包end;
6, rs.pause(); 暂停触发on('data')事件,将流动模式又转化成了非流动模式;
7, on data事件是循环执行的,直到文件读完;

收藏成功!
已添加到「」, 点击更改