node - 流 浅析
概念
流(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 - 流 浅析的更多相关文章
- gulp基于node流的自动化构建工具
GULP 在我才接触gulp的时候 看他就是一个 通过压缩各种文件来提升用户体验的开发工具 那是因为 对他的理解并不深 他真正强大 之处 在于他的 管子 .pipe() 可以 ...
- java中io流浅析
1.java.io包下File类:java程序中的此类的一个对象,就对应着硬盘中的一个文件或网络中的一个资源.File file1 = new File("d:\\io\\helloworl ...
- Node流操作(启动器forever)
详情: https://www.cnblogs.com/lalalagq/p/9749680.html 流:读取流,写入流,双向读写流. 读写流——压缩.加密 数据库不能直接接受流 sf.readFi ...
- Node.js 流
稳定性: 2 - 不稳定 流是一个抽象接口,在 Node 里被不同的对象实现.例如request to an HTTPserver 是流,stdout 是流.流是可读,可写,或者可读写.所有的流是 E ...
- Node.js Streams:你需要知道的一切
Node.js Streams:你需要知道的一切 图像来源 Node.js流以难以使用而闻名,甚至更难理解.好吧,我有个好消息 - 不再是这样了. 多年来,开发人员在那里创建了许多软件包,其唯一目的是 ...
- Node.js 全栈开发(一)——Web 开发技术演化
这些年一直不断接触学习 Node 技术栈,个人的技术开发学习兴趣也越来越倾向 node 流.也许是由于英语的关系,也许是因为墙增加了学习国外一手资料的难度,加上现在流行的 web 开发技术并不太容易上 ...
- DB2 Catalog浅析&学习笔记
原文地址:http://king123654789.iteye.com/blog/1296492 Catalog 是远程连接部署在服务器端的DB2数据库的命令 [本文涉及到的命令] >db2 c ...
- node.学习笔记(关于http2的讲解)
个人总结:读完这篇文章需要30分钟 http2部分很有学习价值,可以好好看. 用node搭建TCP服务器 用node搭建HTTP服务器 用node文件fs模块对文件读取,并用流的方式写入 用url路 ...
- JavaScript资源大全中文版(Awesome最新版--转载自张果老师博客)
JavaScript资源大全中文版(Awesome最新版) 目录 前端MVC 框架和库 包管理器 加载器 打包工具 测试框架 框架 断言 覆盖率 运行器 QA 工具 基于 Node 的 CMS 框 ...
随机推荐
- egret清除缓存的方法
1 图片加版本号2 js加版本号3 default.res.json 加版本号 3个缺一不可 ps: egret 里面default.res.json 资源和代码一定要保持一致
- 数据结构之队列and栈总结分析
一.前言: 数据结构中队列和栈也是常见的两个数据结构,队列和栈在实际使用场景上也是相辅相成的,下面简单总结一下,如有不对之处,多多指点交流,谢谢. 二.队列简介 队列顾名思义就是排队的意思,根据我们的 ...
- 201871010114-李岩松《面向对象程序设计(java)》第二周学习总结
项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...
- X-Admin&ABP框架开发-RBAC
在业务系统需求规划过程中,通常对于诸如组织机构.用户和角色等这种基础功能,通常是将这部分功能规划到通用子域中,这也说明了,对于这部分功能来讲,是系统的基石,整个业务体系是建立于这部分基石之上的,当然, ...
- linux系统LNMP环境部署
源码安装 nginx# yum -y install gcc openssl-devel# useradd -s /sbin/nologin nginx# tar xf nginx-1.14.0.ta ...
- PHP 在Swoole中使用双IoC容器实现无污染的依赖注入
简介: 容器(container)技术(可以理解为全局的工厂方法), 已经是现代项目的标配. 基于容器, 可以进一步实现控制反转, 依赖注入. Laravel 的巨大成功就是构建在它非常强大的IoC容 ...
- 关于 Python 对象拷贝的那点事?
概述 在本篇文章中,会先介绍 Python 中对象的基础概念,之后会提到对象的深浅拷贝以及区别.在阅读后,应该掌握如下的内容: 理解变量.引用和对象的关系 理解 Python 对象中 identity ...
- Python第五天 列表练习 元组类型 字典类型 小购物车练习
# 反转 reverse# l=['lili','asdf','qwer','80000']# l.reverse()# print(l) # ['80000', 'qwer', 'asdf', 'l ...
- 2019-9-26:渗透测试,基础学习,nmap扫描kali虚拟机服务
初识Nmap 1, 首先确定kali的ip地址,输入命令ifconfig 2, 开启所需要扫描的服务, 开启ssh:service ssh start, 确认ssh服务是否开启service ssh ...
- 2019-9-24:渗透测试,JavaScript数据类型基础学习
JavaScript 数据类型 值类型(基本类型):字符串(String).数字(Number).布尔(Boolean).对空(Null).未定义(Undefined).Symbol. 引用数据类型: ...