• stream 模块可以通过以下方式使用:
const stream = require('stream');

流可以是可读的、可写的、或者可读可写的。 所有的流都是 EventEmitter 的实例。

stream 模块本身主要用于开发者创建新类型的流实例。 对于以消费流对象为主的开发者,极少需要直接使用 stream 模块。

  • 可写流(比如例子中的 res)会暴露了一些方法,比如 write() 和 end() 用于写入数据到流。

    当数据可以从流读取时,可读流会使用 EventEmitter API 来通知应用程序。 从流读取数据的方式有很多种。

    可写流和可读流都通过多种方式使用 EventEmitter API 来通讯流的当前状态。

    Duplex 流和 Transform 流都是可写又可读的。

    对于只需写入数据到流或从流消费数据的应用程序,并不需要直接实现流的接口,通常也不需要调用 require('stream')。

流的类型

Node.js 中有四种基本的流类型:

  • Writable - 可写入数据的流(例如 fs.createWriteStream())。
  • Readable - 可读取数据的流(例如 fs.createReadStream())。
  • Duplex - 可读又可写的流(例如 net.Socket)。
  • Transform - 在读写过程中可以修改或转换数据的 Duplex 流(例如 zlib.createDeflate())。

对象模式

Node.js 创建的流都是运作在字符串和 Buffer(或 Uint8Array)上。 当然,流的实现也可以使用其它类型的 JavaScript 值(除了 null)。 这些流会以“对象模式”进行操作。

当创建流时,可以使用 objectMode 选项把流实例切换到对象模式。 将已存在的流切换到对象模式是不安全的。

缓冲

可写流和可读流都会在内部的缓冲器中存储数据,可以分别使用的 writable.writableBuffer 或 readable.readableBuffer 来获取。

可缓冲的数据大小取决于传入流构造函数的 highWaterMark 选项。 对于普通的流,highWaterMark 指定了字节的总数。 对于对象模式的流,highWaterMark 指定了对象的总数。

当调用 stream.push(chunk) 时,数据会被缓冲在可读流中。 如果流的消费者没有调用 stream.read(),则数据会保留在内部队列中直到被消费。

一旦内部的可读缓冲的总大小达到 highWaterMark 指定的阈值时,流会暂时停止从底层资源读取数据,直到当前缓冲的数据被消费 (也就是说,流会停止调用内部的用于填充可读缓冲的 readable._read())。

当调用 writable.write(chunk) 时,数据会被缓冲在可写流中。 当内部的可写缓冲的总大小小于 highWaterMark 设置的阈值时,调用 writable.write() 会返回 true。 一旦内部缓冲的大小达到或超过 highWaterMark 时,则会返回 false。

stream API 的主要目标,特别是 stream.pipe(),是为了限制数据的缓冲到可接受的程度,也就是读写速度不一致的源头与目的地不会压垮内存。

因为 Duplex 和 Transform 都是可读又可写的,所以它们各自维护着两个相互独立的内部缓冲器用于读取和写入, 这使得它们在维护数据流时,读取和写入两边可以各自独立地运作。 例如,net.Socket 实例是 Duplex 流,它的可读端可以消费从 socket 接收的数据,而可写端则可以将数据写入到 socket。 因为数据写入到 socket 的速度可能比接收数据的速度快或者慢,所以在读写两端独立地进行操作(或缓冲)就显得很重要了。

可读流:两种读取模式

可读流运作于两种模式之一:流动模式(flowing)或暂停模式(paused)。

在流动模式中,数据自动从底层系统读取,并通过 EventEmitter 接口的事件尽可能快地被提供给应用程序。

在暂停模式中,必须显式调用 stream.read() 读取数据块。

  • 所有可读流都开始于暂停模式,可以通过以下方式切换到流动模式:
  1. 添加 'data' 事件句柄。
  2. 调用 stream.resume()。
  3. 调用 stream.pipe()。
  • 读流可以通过以下方式切换回暂停模式:
  1. 如果没有管道目标,则调用 stream.pause()。
  2. 如果有管道目标,则移除所有管道目标。调用 stream.unpipe() 可以移除多个管道目标。

只有提供了消费或忽略数据的机制后,可读流才会产生数据。 如果消费的机制被禁用或移除,则可读流会停止产生数据。

为了向后兼容,移除 'data' 事件句柄不会自动地暂停流。 如果有管道目标,一旦目标变为 drain 状态并请求接收数据时,则调用 stream.pause() 也不能保证流会保持暂停模式。

如果可读流切换到流动模式,且没有可用的消费者来处理数据,则数据将会丢失。 例如,当调用 readable.resume() 时,没有监听 'data' 事件或 'data' 事件句柄已移除。

添加 'readable' 事件句柄会使流自动停止流动,并通过 readable.read() 消费数据。 如果 'readable' 事件句柄被移除,且存在 'data' 事件句柄,则流会再次开始流动。

可读流:三种状态

可读流的两种模式是对发生在可读流中更加复杂的内部状态管理的一种简化的抽象。

在任意时刻,可读流会处于以下三种状态之一:

  • readable.readableFlowing === null
  • readable.readableFlowing === false
  • readable.readableFlowing === true

当 readable.readableFlowing 为 null 时,没有提供消费流数据的机制,所以流不会产生数据。 在这个状态下,监听 'data' 事件、调用 readable.pipe()、或调用 readable.resume() 都会使 readable.readableFlowing 切换到 true,可读流开始主动地产生数据并触发事件。

调用 readable.pause()、readable.unpipe()、或接收到背压,则 readable.readableFlowing 会被设为 false,暂时停止事件流动但不会停止数据的生成。 在这个状态下,为 'data' 事件绑定监听器不会使 readable.readableFlowing 切换到 true。

当 readable.readableFlowing 为 false 时,数据可能会堆积在流的内部缓冲中。

可读流:选择一种接口风格

可读流的 API 贯穿了多个 Node.js 版本,且提供了多种方法来消费流数据。 开发者通常应该选择其中一种方法来消费数据,不要在单个流使用多种方法来消费数据。 混合使用 on('data')、on('readable')、pipe() 或异步迭代器,会导致不明确的行为。

对于大多数用户,建议使用 readable.pipe(),因为它是消费流数据最简单的方式。 如果开发者需要精细地控制数据的传递与产生,可以使用 EventEmitter、readable.on('readable')/readable.read() 或 readable.pause()/readable.resume()。

Events: 'finish' and 'end'

'finish'事件来自stream.Writable;'end'事件来自stream.Readable类。

在调用了stream.end()并且stream._transform()处理了全部数据块之后, 'finish'事件触发。

transform._flush()中的回调函数被调用之后,所有数据已经输出,此时,'end'事件触发

node api 之:stream - 流的更多相关文章

  1. Node 中的 stream (流)

    流的概念 流(stream)在 Node.js 中是处理流数据的抽象接口(abstract interface). stream 模块提供了基础的 API .使用这些 API 可以很容易地来构建实现流 ...

  2. node.js中stream流中可读流和可写流的使用

    node.js中的流 stream 是处理流式数据的抽象接口.node.js 提供了很多流对象,像http中的request和response,和 process.stdout 都是流的实例. 流可以 ...

  3. Node.js:Stream(流)

    Stream 是一个抽象接口,Node 中有很多对象实现了这个接口.例如,对http 服务器发起请求的request 对象就是一个 Stream,还有stdout(标准输出). Node.js,Str ...

  4. 理解 Node.js 中 Stream(流)

    Stream(流) 是 Node.js 中处理流式数据的抽象接口. stream 模块用于构建实现了流接口的对象. Node.js 提供了多种流对象. 例如,对 HTTP 服务器的request请求和 ...

  5. 【node.js】Stream(流)

    Stream 有四种流类型: Readable - 可读操作. Writable - 可写操作. Duplex - 可读可写操作. Transform - 操作被写入数据,然后读出结果. 所有的 St ...

  6. Node.js 内置模块Stream(流)

    "流"是一种抽象的数据结构 通过使用"流"可以将一段数据分割成几段,并按顺序传输,使用"流"可以降低对系统性能的要求,减少对CPU的消耗 S ...

  7. 9、Node.js Stream(流)

    #########################################################################介绍Node.js Stream(流)Stream 是 ...

  8. Node.js Stream(流)

    Stream 是一个抽象接口,Node 中有很多对象实现了这个接口.例如,对http 服务器发起请求的request 对象就是一个 Stream,还有stdout(标准输出). Node.js,Str ...

  9. 24.Node.js Stream(流)

    转自:http://www.runoob.com/nodejs/nodejs-stream.html Stream 是一个抽象接口,Node 中有很多对象实现了这个接口.例如,对http 服务器发起请 ...

随机推荐

  1. transform带来的坑

    1.transform会使子元素fixed定位和absolute定位失效. 2.父元素设置了border-radius和overflow:hidden, 但是子元素有transform属性,父元素设置 ...

  2. L264 how cats are psychopaths

    When Becky Evans started studying cat-human relationships, she kept hearing, over and over again, ab ...

  3. WIN10-缩放与布局

    HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics\AppliedDPI230%----- 221225%----- 218220%----- ...

  4. lvs的FULLNAT

  5. java学习笔记19(Arrays类)

    Arrays类: 此类包含用来操作数组的各种方法(比如升序和搜索): import java.util.Arrays; public class Demo { public static void m ...

  6. python2.6.6 升级 2.7.X

    下载包 解压 cd 进入 ./configure && make all && make install && make clean && ...

  7. idea【取消多行】

    有时间把idea总结一下 idea打开很多文件时默认收起来就很烦. 这样可以取消多行 效果大概是这样 .酥服哒.

  8. Python中的print、input函数以及Python中交换两个变量解析

    一.Python中的值交换操作 首先明确一点点,Python中的一切都是面向对象的,可以理解为Python的中一切都是对象. 我们知道Java也是面向对象的语言,但是在Java中定义一个值变量如下: ...

  9. Python之路PythonNet,第四篇,网络4

    pythonnet   网络4 select  支持水平触发 poll       支持水平触发 epoll epoll 也是一种IO多路复用的方式,效率比select和poll 要高一点: epol ...

  10. c#网站文件下载次数统计

    参考:http://q.cnblogs.com/q/17954/ 项目中需要准确记录文件的下载次数,和帖子的要求差不多. 参考了帖子中推荐的链接,问题得到了有效控制. 大概方法:逐字节(大小可以自己控 ...