node api 之:stream - 流
- 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() 读取数据块。
- 所有可读流都开始于暂停模式,可以通过以下方式切换到流动模式:
- 添加 'data' 事件句柄。
- 调用 stream.resume()。
- 调用 stream.pipe()。
- 读流可以通过以下方式切换回暂停模式:
- 如果没有管道目标,则调用 stream.pause()。
- 如果有管道目标,则移除所有管道目标。调用 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 - 流的更多相关文章
- Node 中的 stream (流)
流的概念 流(stream)在 Node.js 中是处理流数据的抽象接口(abstract interface). stream 模块提供了基础的 API .使用这些 API 可以很容易地来构建实现流 ...
- node.js中stream流中可读流和可写流的使用
node.js中的流 stream 是处理流式数据的抽象接口.node.js 提供了很多流对象,像http中的request和response,和 process.stdout 都是流的实例. 流可以 ...
- Node.js:Stream(流)
Stream 是一个抽象接口,Node 中有很多对象实现了这个接口.例如,对http 服务器发起请求的request 对象就是一个 Stream,还有stdout(标准输出). Node.js,Str ...
- 理解 Node.js 中 Stream(流)
Stream(流) 是 Node.js 中处理流式数据的抽象接口. stream 模块用于构建实现了流接口的对象. Node.js 提供了多种流对象. 例如,对 HTTP 服务器的request请求和 ...
- 【node.js】Stream(流)
Stream 有四种流类型: Readable - 可读操作. Writable - 可写操作. Duplex - 可读可写操作. Transform - 操作被写入数据,然后读出结果. 所有的 St ...
- Node.js 内置模块Stream(流)
"流"是一种抽象的数据结构 通过使用"流"可以将一段数据分割成几段,并按顺序传输,使用"流"可以降低对系统性能的要求,减少对CPU的消耗 S ...
- 9、Node.js Stream(流)
#########################################################################介绍Node.js Stream(流)Stream 是 ...
- Node.js Stream(流)
Stream 是一个抽象接口,Node 中有很多对象实现了这个接口.例如,对http 服务器发起请求的request 对象就是一个 Stream,还有stdout(标准输出). Node.js,Str ...
- 24.Node.js Stream(流)
转自:http://www.runoob.com/nodejs/nodejs-stream.html Stream 是一个抽象接口,Node 中有很多对象实现了这个接口.例如,对http 服务器发起请 ...
随机推荐
- Linux文件系统命令 rm
命令名:rm 功能:删除某一个文件或者目录 eg: renjg@renjg-HP-Compaq-Pro--MT:~/WorkSpace$ ls BM3 gf k8s minicom_download ...
- input获取焦点无效
js控制input获得焦点: $("input").focus(); 无效,写在延时函数中问题解决: setTimeout(function(){ $("input&qu ...
- table 表头固定 thead固定. 1) 使用jquery.freezeheader.js
方法一: 使用jquery.freezeheader.js 固定表头: 1-: 初始化: <!DOCTYPE html> <html lang="en"> ...
- chromium ①
Chrome源码剖析 [序] && [一] 1. 它是如何利用多进程(其实也会有多线程一起)做并发的, 进程间通信,进程的开销:2. 做为一个后来者,它的扩展能力如何 3. 它的整体框 ...
- python自学第6天,文件修改,字符编码
文件的修改: 一般是把旧文件的内容改了,在写入到新的文件中去. file_old=open("test","r",encoding="utf-8&qu ...
- linux 断网 扫描基本命令
kali使用arpspoof命令进行ARP欺骗. 做法是获取目标主机IP镜像流量,再进行ARP欺骗. 此次测试实在局域网中进行,使用kali虚拟机和Windows10物理机测试. 最终效果是利用kal ...
- ajax异步上传图片(TP5)
直接上代码 PHP代码如下 /** * 上传 */ public function upload_photo(){ $file = $this->request->file('file') ...
- POJ 1287 Networking(最小生成树裸题有重边)
Description You are assigned to design network connections between certain points in a wide area. Yo ...
- Spring Boot 揭秘与实战(五) 服务器篇 - Tomcat 启用 HTTPS
文章目录 1. 生成证书 2. 配置 HTTPS 支持 3. 启动与测试 4. 源代码 Spring Boot 内嵌的 Tomcat 服务器可以启用 HTTPS 支持. 生成证书 使用第三方 CA 证 ...
- [转][译] Closures in Lua - Lua中的闭包
http://www.cnblogs.com/plodsoft/p/5900270.html?utm_source=tuicool&utm_medium=referral 原文:(PDF) . ...