【第2章 Node.js基础】2.7 Node.js 的流(一) 可读流

🌈 Node.js 的流

🚀什么是流

流不是 Node.js 特有的概念。它们是几十年前在 Unix 操作系统中引入的。

我们可以把流看作这些数据的集合,就像液体一样,我们先把这些液体保存在一个容器里(流的内部缓冲区 BufferList),等到相应的事件触发的时候,我们再把里面的液体倒进管道里,并通知其他人在管道的另一侧拿自己的容器来接里面的液体进行处理。

在这里插入图片描述

Node.js中的流是一种处理数据的抽象接口,它提供了一种有效的方式(按需处理数据)来读取或写入大量数据,而无需一次性将整个数据加载到内存中。流可以被视为数据在某段时间内从一个点移动到另一个点的序列,类似于水从一根管子的一端流到另一端。

🚀Node.js流的好处

Node.js流解决了处理大量数据时可能遇到的内存消耗和性能问题。以下是使用Node.js流的好处:

  1. 内存效率:使用流可以按需处理数据,而不需要一次性将整个数据加载到内存中。这意味着即使处理大量数据,也可以节省大量的内存空间。流以块的形式处理数据,每次只加载和处理一小部分数据,然后将其释放,从而减少了内存的使用量。

  2. 性能优化:由于流以块的形式处理数据,可以实现并行处理,提高处理速度。流还可以通过流水线(pipeline)的方式将多个操作连接起来,实现数据的连续处理,从而提高整体性能。

  3. 响应性:使用流可以实现实时处理数据,即在数据到达时立即进行处理,而不需要等待整个数据加载完成。这对于需要实时处理数据的应用程序非常重要,例如实时日志分析、实时聊天等。

  4. 可扩展性:流是可组合的,可以将多个流连接起来形成更复杂的数据处理流程。这种可组合性使得代码更加模块化和可重用,便于扩展和维护。

  5. 适用于各种场景:Node.js流可以用于处理各种类型的数据,包括文件、网络请求、数据库查询结果等。无论是处理大文件、处理网络请求还是处理数据库查询结果,使用流都可以提供高效的数据处理方式。

🚀Node.js流的重点知识

以下是关于Node.js流的重点知识点总结:

  1. 流的类型:流可以是可读的、可写的,或者可读可写的。在Node.js中,有四种内置的流类型,
    1. 可读流(Readable)、
    2. 可写流(Writable)、
    3. 双工流(Duplex)
    4. 转换流(Transform)。
  2. 常见的流事件:所有的流都是EventEmitter类的实例,可以通过事件和方法来处理流的数据。
    1. data(当有数据可读时触发)、
    2. end(当没有更多数据可读时触发)
    3. error(当发生错误时触发)等。
  3. 常见的流方法包括
    1. write(向流中写入数据)
    2. read(从流中读取数据)
    3. pipe(将一个可读流的数据传输到一个可写流)等。
  4. 流的工作原理:流将要传输的数据处理成连续的块(chunk),通过一小块一小块地传输数据,从而降低内存消耗并提高性能。这种逐段处理的方式使得流非常适合处理大量数据或需要逐段处理的场景。
  5. 内置的流对象:Node.js中有许多内置的流对象,如HTTP请求、文件读写、标准输入输出(stdin/stdout)等。这些内置的流对象可以直接使用,无需直接实现流的接口。
  6. stream模块:stream模块是用于构建实现流接口的对象的模块,可以通过require('stream')导入。开发人员可以使用stream模块创建自定义的流实例,实现更复杂的流操作。

🌈 可读流

🚀什么是可读流

可读流是对提供数据的来源的一种抽象。可读流的例子包括客户端的 HTTP 响应、服务器的 HTTP请求、fs 的读取流、zlib 流、crypto 流、TCP Socket、子进程 stdout与stderr、process.stdin 等。所有可读流都实现了 stream.Readable 类定义的接口。

fs读取文件案例

文件:fs读取文件.js

const fs = require("fs");
// 创建可读流
const rs = fs.createReadStream("./movie.txt");let content = "";
// 当有数据可读时触发"data"事件
rs.on("data", chunk => {// 将读取的数据块拼接到content变量中content += chunk;
});// 当可读流结束时触发"end"事件
rs.on("end", () => {// 所有数据已读取完毕,输出content内容console.log(content);
});

文件:movie.txt

The best time to plant a tree is 20 years ago. 
The second-best time is now.
种一棵树最好的时间是20年前,
其次是现在

输出结果

PS D:\WuWorkSpace\code\NodejsProject\nodejs实战学习\【第2章  Node.js基础】\2.7 Node的流> node .\fs可读流.js
The best time to plant a tree is 20 years ago.
The second-best time is now.
种一棵树最好的时间是20年前,
其次是现在
process.stdin案例
 process.stdin.pipe(process.stdout);

这段代码使用了Node.js的process.stdinprocess.stdout流对象,并通过pipe方法将输入流(process.stdin)的数据直接传输到输出流(process.stdout)中。

具体解析如下:

  • process.stdin是一个可读流,它表示标准输入流(stdin),可以用于接收用户的输入。
  • process.stdout是一个可写流,它表示标准输出流(stdout),可以用于向控制台输出数据。

通过调用pipe方法,我们将输入流(process.stdin)连接到输出流(process.stdout),这样输入流中的数据会被自动传输到输出流中。

这段代码的作用是将用户在控制台输入的内容直接输出到控制台,实现了一个简单的输入输出的管道(复读机)。

动图演示如下

在这里插入图片描述

http案例

客户端的 HTTP 响应、服务器的 HTTP请求是可读流。

服务端文件:http-server.js

const http = require("http");
const server = http.createServer((req,res)=>{if(req.method === "POST" && req.url.includes("/upload")){process.stdout.write("服务端收到了请求:");// req 服务器的 HTTP 请求(可读流)req.pipe(process.stdout);// res 服务器的 HTTP 响应(可写流)res.write("我是服务端响应");res.end();}else{res.writeHead(404);res.end("Not Found");}
})
server.listen(9800);
console.log(`服务已经运行在:http://localhost:9800`);

客户端代码文件:http-client.js

const http = require("http");
const options = {hostname : "127.0.0.1",port : 9800,path : "/upload",method : "POST"
};
const req = http.request(options,res=>{process.stdout.write("客户端获取响应:");// res 客户端的 HTTP 响应(可读流)res.pipe(process.stdout);
})// req 客户端的 HTTP 请求(可写流)
req.write("我是客户端。");
req.end();

以下是运行演示:先运行服务端代码 http-server.js ,再运行客户端代码http-client.js

$ node .\http-client.js
客户端获取响应:我是服务端响应
$ node .\http-server.js
服务已经运行在:http://localhost:9800
服务端收到了请求:我是客户端。

··在这里插入图片描述

🚀可读流de两种模式

可读流有两种模式:流动(Flowing)和暂停(Paused )。在流动模式中,数据被自动从底层系统读取,并通过 EventEmitter 接口的事件尽可能快地提供给应用程序。在暂停模式中,必须显式调用stream.read()方法读取数据块。
所有可读流一开始都处于暂停模式,,之后可以通过以下方式切换到流动模式。

  • 添加data 事件处理函数。
  • 调用stream.resume()方法。
  • 调用 stream.pipe()方法。

可读流也可以通过以下方式切换回暂停模式。

  • 如果没有管道目标,则调用 stream.pause()方法
  • 如果有管道目标,则移除所有管道目标。调用 stream.unpipe()方法可以移除多个管道目标。

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

stream.Readable类定义的主要事件:

  • data:当有数据可读时被触发。
  • end:没有更多的数据可读时被触发。
  • close:当流或其底层资源被关闭时被触发。

stream.Readable 类定义的主要方法

  • readable.read([size]):从内部缓冲区拉取并返回数据。
  • readable.pause():使流动模式的流停止触发data事件,并切换出流动模式。
  • readable.setEncoding(encoding):为从可读流读取的数据设置字符编码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/145403.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JS原生-弹框+阿里巴巴矢量图

效果&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content&q…

【题解】洛谷 P9658 Laser Trap

题解-P9658 Laser Trap 题目传送门 题意简述 题面是英文的&#xff0c;还没翻译&#xff0c;就讲一讲吧。 n n n 个激光发射器&#xff0c;两两之间产生激光束&#xff0c;将平面分为若干区域。 问至少删去多少个发射器&#xff0c;可以使得原点与外侧区域联通。 多组数据&a…

Java封装一个根据指定的字段来获取子集的工具类

工具类 ZhLambdaUtils SuppressWarnings("all") public class ZhLambdaUtils {/*** METHOD_NAME*/private static final String METHOD_NAME "writeReplace";/*** 获取到lambda参数的方法名称** param <T> parameter* param function functi…

excel导入 Easy Excel

依旧是框架感觉有东西&#xff0c;但是确实是模拟不出来&#xff0c;各种零零散散的件太多了 controller层 ApiOperation(value "导入Excel", notes "导入Excel", httpMethod "POST", response ExcelResponseDTO.class)ApiImplicitParams({…

Unity3d 导入中文字体转TMPtext asset

外部字体放入unity仓库以后呢&#xff0c;需要把这个字体转成用立体的字体文件才可以被使用&#xff01; 要想转换的话呢先放入仓库对字体点右键上面有一个Create创建里面有一个TEXT Asset&#xff0c;创建好就可以使用了

(论文阅读32/100)Flowing convnets for human pose estimation in videos

32.文献阅读笔记 简介 题目 Flowing convnets for human pose estimation in videos 作者 Tomas Pfister, James Charles, and Andrew Zisserman, ICCV, 2015. 原文链接 https://arxiv.org/pdf/1506.02897.pdf 关键词 Human Pose Estimation in Videos 研究问题 视频…

leetcode刷题日志-58最后一个单词的长度

给你一个字符串 s&#xff0c;由若干单词组成&#xff0c;单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。 单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。 示例 1&#xff1a; 输入&#xff1a;s “Hello World” 输出&#xff1a;5 解释&a…

spring为什么要使用三级缓存来解决循环依赖

出现循环依赖的原因 AService依赖BService Service("aService") public class AService {AutowiredBService bService; } BService依赖AService Service("bService") public class BService {AutowiredAService aService; } 此时就出现了循环依赖 想…

应用软件安全编程--17预防基于 DOM 的 XSS

DOM型XSS从效果上来说也属于反射型XSS,由于形成的原因比较特殊所以进行单独划分。在网站页面中有许多页面的元素&#xff0c;当页面到达浏览器时浏览器会为页面创建一个顶级的Document object 文档对象&#xff0c;接着生成各个子文档对象&#xff0c;每个页面元素对应一个文档…

11.16 知识总结(模型层更多内容)

一、 多表查询&#xff08;跨表查询&#xff09; <br class"Apple-interchange-newline"><div></div> 子查询&#xff1a;分步查询 链表查询&#xff1a;把多个有关系的表拼接成一个大表(虚拟表) inner join left join right join 1.1 基于双下划…

【2016年数据结构真题】

已知由n&#xff08;M>2&#xff09;个正整数构成的集合A{a<k<n},将其划分为两个不相交的子集A1 和A2&#xff0c;元素个数分别是n1和n2&#xff0c;A1和A2中的元素之和分别为S1和S2。设计一个尽可能高效的划分算法&#xff0c;满足|n1-n2|最小且|s1-s2|最大。要求…

Ubuntu16.04上安装Docker

Ubuntu16.04上安装Docker 更新 apt 包索引: sudo apt-get update安装依赖包,以便使用 HTTPS 仓库 sudo apt-get install apt-transport-https ca-certificates curl software-properties-common添加 Docker GPG 密钥 curl -fsSL https://download.docker.com/linux/ubuntu…

JVM——运行时数据区(堆+方法区+直接内存)

目录 1.Java堆2.方法区**方法区&#xff08;Method Area&#xff09;溢出**方法区&#xff08;Method Area&#xff09;字符串常量池静态变量的存储 3.直接内存(Direct Memory) 1.Java堆 ⚫ 一般Java程序中堆内存是空间最大的一块内存区域。创建出来的对象都存在于堆上。 ⚫ 栈…

matlab二维曲面散点图插值方法

在 MATLAB 中&#xff0c;你可以使用以下函数进行二维曲面散点插值&#xff1a; griddata: 该函数可以在散点数据上进行二维插值&#xff0c;生成平滑的曲面。它支持多种插值方法&#xff0c;包括三次样条插值、最近邻插值、线性插值和自然邻近法插值。 scatteredInterpolant:…

update与merge基本语法规则、异同点、使用场景

– UPDATE更新数据SQL UPDATE /append parallel(A,8) nologging/ CRSMAK.M_CM_GS_BILL_DISH_INFO A --票据贴现信息 SET A.YEAR_PAR_AMT (SELECT /parallel(B,8)/ YEAR_PAR_AMT FROM (SELECT BIZ_ID, SUM(NVL(PAR_AMT, 0)) YEAR_PAR_AMT --年累计票面金额 FROM CRSMAK.M_CM_G…

存钱虚拟计划,嘚

存钱计划—虚拟 2024年 (第一年) 1月 2月 3月 4月 5月 6 月 7月 8月 9月 10月 11月 12月 1w 1w 1w 1w 1w 1w 1w 1w 1w 1w 1w 1w 2025年(第二年) 1w1w*102.5% A 懒得写A代替 A A A A A A A A A A 2026年(第三年) (1w1w*10…

Centos7.9用rancher来快速部署K8S

什么是 Rancher&#xff1f; Rancher 是一个 Kubernetes 管理工具&#xff0c;让你能在任何地方和任何提供商上部署和运行集群。 Rancher 可以创建来自 Kubernetes 托管服务提供商的集群&#xff0c;创建节点并安装 Kubernetes&#xff0c;或者导入在任何地方运行的现有 Kube…

React路由跳转但是页面未发生改变,刷新后正常显示

react项目&#xff0c;配置好路由后&#xff0c;触发跳转发现url已经改变但页面内容未改变&#xff0c;刷新后才能正常显示。 发现是被react的严格模式影响&#xff0c;将BrwserRouter放到其外层即可 const root ReactDOM.createRoot(document.getElementById("root&qu…