概念

流(stream)是 Node.js 中处理流式数据的抽象接口。 stream 模块用于构建实现了流接口的对象。

Node.js 提供了多种流对象。 例如,HTTP 服务器的请求和 process.stdout 都是流的实例。

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

访问 stream 模块:

const stream = require('stream');

尽管理解流的工作方式很重要,但是 stream 模块主要用于开发者创建新类型的流实例。 对于以消费流对象为主的开发者,极少需要直接使用 stream 模块。

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

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

此外,该模块还包括实用函数 stream.pipeline()、stream.finished() 和 stream.Readable.from()。

盗图

如何获取内存中的流

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

细节

可读流

两种模式

  • 流动模式(不用打,自己动):数据自动从底层系统读取,并通过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 事件句柄,则流会再次开始流动

demo

流动模式

const fs = require('fs')
const path = require('path')
const rs = fs.createReadStream(path.join(__dirname, './1.txt')) rs.setEncoding('utf8') rs.on('data', (data) => {
console.log(data)
})

暂停模式

const fs = require('fs')
const path = require('path')
const rs = fs.createReadStream(path.join(__dirname, './1.txt')) rs.setEncoding('utf8') rs.on('readable', () => {
let d = rs.read(1) // 要读取的数据的字节数。
console.log(d)
})

read方法: 参数 可选 [size]

如果没有指定 size 参数,则返回内部缓冲中的所有数据。

使用 readable.read() 处理数据时, while 循环是必需的。

read方法消耗的是内存中的数据

当read方法返回的是null的时候,会触发 流监听的 end 事件

不使用read消耗内存中的流数据,则不会触发end

预览一波

遇到的问题

process.stdin.setEncoding('utf8');

process.stdin.on('readable', () => {
let chunk;
while ((chunk = process.stdin.read()) !== null) {
process.stdout.write(`数据: ${chunk}长度${chunk.length}\n`);
}
}); process.stdin.on('end', () => {
process.stdout.write('结束\n');
process.exit(1);
});

上面的代码作用是读取用户在terminal上的输出,然后输出内容和长度,但是执行的时候,总是无法执行到end,不仅如此,就算内容为空,返回的长度也不为0,这让我很疑惑。

最后发现是坚挺的end事件,只有当read方法返回为null的时候才会触发,所以没有触发,而问题就在于返回的内容是换行符,不同系统下换行符不一样,mac下是\n,所以我们需要处理一下read返回的内容,然后手动end

查看字符串中回车符可以使用:

console.log(JSON.stringify(chunk));

修正后的代码为:

process.stdin.setEncoding('utf8');

process.stdin.on('readable', () => {
let chunk;
while ((chunk = process.stdin.read()) !== null) {
chunk = chunk.replace(/\n/g, '');
if (!chunk.length) {
console.log('输入为空');
return process.stdin.emit('end');
}
process.stdout.write(`数据: ${chunk}长度${chunk.length}\n`);
}
}); process.stdin.on('end', () => {
process.stdout.write('结束\n');
process.exit(1);
});

执行结果:

中文文档

node - 流 浅析的更多相关文章

  1. gulp基于node流的自动化构建工具

    GULP 在我才接触gulp的时候 看他就是一个 通过压缩各种文件来提升用户体验的开发工具   那是因为  对他的理解并不深    他真正强大 之处 在于他的     管子  .pipe()  可以 ...

  2. java中io流浅析

    1.java.io包下File类:java程序中的此类的一个对象,就对应着硬盘中的一个文件或网络中的一个资源.File file1 = new File("d:\\io\\helloworl ...

  3. Node流操作(启动器forever)

    详情: https://www.cnblogs.com/lalalagq/p/9749680.html 流:读取流,写入流,双向读写流. 读写流——压缩.加密 数据库不能直接接受流 sf.readFi ...

  4. Node.js 流

    稳定性: 2 - 不稳定 流是一个抽象接口,在 Node 里被不同的对象实现.例如request to an HTTPserver 是流,stdout 是流.流是可读,可写,或者可读写.所有的流是 E ...

  5. Node.js Streams:你需要知道的一切

    Node.js Streams:你需要知道的一切 图像来源 Node.js流以难以使用而闻名,甚至更难理解.好吧,我有个好消息 - 不再是这样了. 多年来,开发人员在那里创建了许多软件包,其唯一目的是 ...

  6. Node.js 全栈开发(一)——Web 开发技术演化

    这些年一直不断接触学习 Node 技术栈,个人的技术开发学习兴趣也越来越倾向 node 流.也许是由于英语的关系,也许是因为墙增加了学习国外一手资料的难度,加上现在流行的 web 开发技术并不太容易上 ...

  7. DB2 Catalog浅析&学习笔记

    原文地址:http://king123654789.iteye.com/blog/1296492 Catalog 是远程连接部署在服务器端的DB2数据库的命令 [本文涉及到的命令] >db2 c ...

  8. node.学习笔记(关于http2的讲解)

    个人总结:读完这篇文章需要30分钟 http2部分很有学习价值,可以好好看.  用node搭建TCP服务器 用node搭建HTTP服务器 用node文件fs模块对文件读取,并用流的方式写入 用url路 ...

  9. JavaScript资源大全中文版(Awesome最新版--转载自张果老师博客)

    JavaScript资源大全中文版(Awesome最新版)   目录 前端MVC 框架和库 包管理器 加载器 打包工具 测试框架 框架 断言 覆盖率 运行器 QA 工具 基于 Node 的 CMS 框 ...

随机推荐

  1. Pycharm创建项目时 自动添加头部信息

    1.打开PyCharm,选择File--Settings 2.依次选择Editor---Code Style-- File and Code Templates---Python Script 3.. ...

  2. linux下安装opencv3.0

    查版本gcc --version 需>4.8python 2.7+cmake --version numpy 以上是必须的 linux下安装opencv3.0<pre>https:/ ...

  3. FileStream相关知识分享

    一.如何理解FIleStream 通过前3章的学些,相信大家对于Stream已经有一定的了解,但是又如何去理解FileStream呢?请看下图: 我们磁盘中的任何文件都是通过二进制数组组成,最为直观的 ...

  4. 【algo&ds】1.时间复杂度和空间复杂度分析

    1.时间复杂度分析O(f(n)) 分析方法 只关注循环执行次数最多的一段代码 加法原则 乘法原则 高优先级原则 常见时间复杂度量级 多项式量级和非多项式量级.其中,非多项式量级只有两个:O(2^n) ...

  5. iOS定位--CoreLocation

    一:导入框架 #import <CoreLocation/CoreLocation.h> 二:设置代理及属性 <CLLocationManagerDelegate> @prop ...

  6. [Office] 显示Office 2013中的Developer Tab和启用Macro

    显示Developer Tab是对Office 2013进行开发的前提条件. 在Excel 2013中,打开Excel Option: 只要勾选对应的Developer选项即可显示该tab. 随着Of ...

  7. jenkins手把手教你从入门到放弃03-安装Jenkins时web界面出现该jenkins实例似乎已离线

    简介 很久没有安装jenkins了,因为之前用的的服务器一直正常使用,令人郁闷的是,之前用jenkins一直没出过这个问题. 令人更郁闷的是,我尝试了好多个历史版本和最新版本,甚至从之前的服务器把je ...

  8. nyoj 275-队花的烦恼一 (stack, push, pop)

    275-队花的烦恼一 内存限制:64MB 时间限制:3000ms 特判: No 通过数:11 提交数:14 难度:1 题目描述: ACM队的队花C小+经常抱怨:“C语言中的格式输出中有十六.十.八进制 ...

  9. 多线程编程(3)——synchronized原理以及使用

    一.对象头 通常在java中一个对象主要包含三部分: 对象头 主要包含GC的状态..类型.类的模板信息(地址).synchronization状态等,在后面介绍. 实例数据:程序代码中定义的各种类型的 ...

  10. TestNG+Maven+IDEA 环境配置+入门

    一.环境配置 1.安装IDEA(参考:https://blog.csdn.net/m0_38075425/article/details/80883078) 2.在Prefernces,通过Plugi ...