最近学习使用Node.js创建http proxy server,少不了要跟Stream打交道。昨天开始查阅一些资料,多少有了一些粗浅了解。整理在这里,供学习之用。

  从Node.js API文档中可知,

  "A stream is an abstract interface implemented by various objects in Node. For example a request to an HTTP server is a stream, as is stdout. Streams are readable, writable, or both. All streams are instances of EventEmitter。""流是很多I/0操作的抽象,被 Node 中的很多对象所实现。比如对一个 HTTP 服务器的请求是一个流(可读流)(服务器的响应是一个流(可写流)),stdout也是流。流是可读、可写或兼具两者的。所有流都是 EventEmitter 的实例。"

一.  为什么需要流(Stream)?

  举个例子,如果要读取一个文件,一次性读取需要占用大内存,是不可取的。因此就有了流,用流会很方便,可以帮我们避免这样的问题,调用其接口不用关心底层如何实现。

二. 什么是流(Stream)?

  流(Stream)是可读,可写或双工的。可以通过require('stream')加载流的基类,其中包括四类流, Readable 流、Writable 流、Duplex 流和Transform 流的基类。

  

  另外如果觉得上述四类基类流不能满足需求,可以编写自己的扩充类流。像我们Team现在正做的Node项目,就重写了Transform类以供使用。

  按照官方的API文档,步骤如下:

  1. 在您的子类中扩充适合的父类。(例如util.inherits(MyTransform, Transform); )
  2. 在您的构造函数中调用父类的构造函数,以确保内部的机制被正确初始化。
  3. 实现一个或多个特定的方法,参见下面的细节。 

     

三. Readable流(可读流)介绍

   Readable(可读)流接口是对您正在读取的数据的来源的抽象。换言之,数据出自一个可读流。

   Readable 流有两种“模式”:流动模式暂停模式

   当处于流动模式时,数据由底层系统读出,并尽可能快地提供给您的程序;当处于暂停模式时,您必须明确地调用 stream.read() 来取出若干数据块。流默认处于暂停模式。

 

   A. 通过以下三种方法,可读流会被切换到流动模式

     1. 添加一个'data'事件处理器来监听数据。

     2. 调用 resume()方法来明确开启数据流。

  3. 调用 pipe()方法将数据发送到一个可写流(Writable)。

     之前我一直对pipe()方法有疑问,不清楚其用法。现在了解,当我们用pipe()为可读流指定了一个接受者(可写流)的时候,数据才会真正的被从底层系统读出,传递给可写流。

  

   B. 下面介绍Readable流有以下几种事件

     1. 'Readable'事件

     2. 'data'事件 - 数据正在传递时,触发该事件(以chunk数据块为对象)

     3. 'end'事件 - 数据传递完成后,会触发该事件。

     4. 'close'事件

     5. 'error'事件

     所有这些事件都可以在官方API文档中找到例子。

    C. 下面介绍Readable流很重要的一个方法,pipe()方法。

     该方法从可读流中拉取所有数据,并写入到所提供的目标(可写流)。该方法能自动控制流量以避免目标被快速读取的可读流所淹没。

     值得注意的是,默认情况下,当数据传送完毕,触发'end'事件时,会同时触发目标(可写流)的'end'事件,导致目标不再可写。

   举个简单的小例子,

 //http.js

 var http = require('http');
var fs = require('fs'); http.createServer(function(req, res){
var stream = fs.createReadStream(__dirname + '/data.txt');
stream.pipe(res);
}).listen(3000); console.log('now we are listening 3000 port');

     data.txt文件内容如下:

    

     当执行此段代码后,用户访问http://127.0.0.1:3000/,会得到如下响应:

     

   此时,创建此Server后,用户访问请求过来,Server会创建一个可读流,当调用stream.pipe(res)为可读流指定目标后,可读流stream会开始从文件data.txt中读取数据,数据写入res(可写流)完毕后,自动调用res的end()方法,结束响应,可写流不再写入。

四. Writable流(可写流)介绍

   Writable(可写)流接口是对写入数据的目标的抽象。

   可写流重要的两个方法,

   1. write()方法

     该方法向底层系统写入数据,并在数据被处理完毕后调用所给的回调。

   2. end()方法

   当不再写入数据时,调用该方法,停止写入。在调用end()后,再调用write()方法会产生错误。

五. 参考资料

   1. Node.js官方API文档

   http://www.nodejs.org/api/stream.html

   2. 官方API文档中文版

   http://nodeapi.ucdok.com/#/api/stream.html

   3. Node 中的流(Stream)

     http://blog.segmentfault.com/xingrz/1190000000357044

   4. Node Streams: How do they work?

   http://maxogden.com/node-streams.html

  抛砖引玉,继续加油。

  Best Regards

  Kevin Song 

                                                                                 - 2014/6/18

    

最新文章

  1. React学习笔记-8-属性和状态详解
  2. Best 3D Modeling software under Ubuntu
  3. Rsync+lsync实现触发式实时同步
  4. 根据不同的屏幕宽度引入不同的css文件
  5. iOS8 超简单的设置圆角按钮 ImageView等UIView
  6. jszs 枚举算法
  7. ambari的重新安装
  8. <转>四个重要属性——Action、Data、Category、Extras
  9. 通过Transaction Log(fn_dblog)取回被删除的数据
  10. Jmeter自动化测试工具的简单使用--HTTP测试
  11. vue学习笔记(1)—— 组件化实现todoList
  12. ubuntu中运行python脚本
  13. 如何判断Linux 是32位还是64位
  14. python爬虫小结1
  15. vue启动报错
  16. Kettle Spoon入门教程
  17. postman操作练习用例
  18. Travel notes in Vietnam
  19. centos7设置时间和时区
  20. 10.5Djang admin 管理工具

热门文章

  1. 【论文】CornerNet:几点疑问
  2. linux系统安全加固--账号相关
  3. Java8 流的使用示例
  4. Linux 防火墙iptables 实例
  5. PHP、thinkPHP5.0开发网站文件管理功能(三)重命名文件
  6. SpringBoot初始教程之Servlet、Filter、Listener配置详解
  7. JavaSE---位运算符
  8. pip安装flask问题解决
  9. Docker Ubuntu/CentOS 下运行 java jar
  10. C++(SOCKET)简单爬虫制作