node中的Stream

本文深入探讨Node.js中的Stream,包括它的定义、四种类型:可读、可写、双工和转换流,以及在处理HTTP请求、文件操作和构建工具中的实际应用场景。通过实例代码展示了如何使用Stream进行数据传输,帮助理解其工作原理。

一、是什么

流(Stream),是一个数据传输手段,是端到端信息交换的一种方式,而且是有顺序的,是逐块读取数据、处理内容,用于顺序读取输入或写入输出

Node.js中很多对象都实现了流,总之它是会冒数据(以 Buffer 为单位)

它的独特之处在于,它不像传统的程序那样一次将一个文件读入内存,而是逐块读取数据、处理其内容,而不是将其全部保存在内存中

流可以分成三部分:sourcedestpipe

sourcedest之间有一个连接的管道pipe,它的基本语法是source.pipe(dest)sourcedest就是通过pipe连接,让数据从source流向了dest,如下图所示:

二、种类

NodeJS,几乎所有的地方都使用到了流的概念,分成四个种类:

  • 可写流:可写入数据的流。例如 fs.createWriteStream() 可以使用流将数据写入文件
  • 可读流: 可读取数据的流。例如fs.createReadStream() 可以从文件读取内容
  • 双工流: 既可读又可写的流。例如 net.Socket
  • 转换流: 可以在数据写入和读取时修改或转换数据的流。例如,在文件压缩操作中,可以向文件写入压缩数据,并从文件中读取解压数据

NodeJSHTTP服务器模块中,request 是可读流,response 是可写流。还有fs 模块,能同时处理可读和可写文件流

可读流和可写流都是单向的,比较容易理解,而另外两个是双向的

双工流

之前了解过websocket通信,是一个全双工通信,发送方和接受方都是各自独立的方法,发送和接收都没有任何关系

如下图所示:

基本代码如下:

const { Duplex } = require('stream');

const myDuplex = new Duplex({read(size) {// ...},write(chunk, encoding, callback) {// ...}
}); 

双工流

双工流的演示图如下所示:

除了上述压缩包的例子,还比如一个 babel,把es6转换为,我们在左边写入 es6,从右边读取 es5

基本代码如下所示:

const { Transform } = require('stream');

const myTransform = new Transform({transform(chunk, encoding, callback) {// ...}
}); 

三、应用场景

stream的应用场景主要就是处理IO操作,而http请求和文件操作都属于IO操作

试想一下,如果一次IO操作过大,硬件的开销就过大,而将此次大的IO操作进行分段操作,让数据像水管一样流动,直到流动完成

常见的场景有:

  • get请求返回文件给客户端
  • 文件操作
  • 一些打包工具的底层操作

get请求返回文件给客户端

使用stream流返回文件,res也是一个stream对象,通过pipe管道将文件数据返回

const server = http.createServer(function (req, res) {const method = req.method; // 获取请求方法if (method === 'GET') { // get 请求const fileName = path.resolve(__dirname, 'data.txt');let stream = fs.createReadStream(fileName);stream.pipe(res); // 将 res 作为 stream 的 dest}
});
server.listen(8000); 

文件操作

创建一个可读数据流readStream,一个可写数据流writeStream,通过pipe管道把数据流转过去

const fs = require('fs')
const path = require('path')

// 两个文件名
const fileName1 = path.resolve(__dirname, 'data.txt')
const fileName2 = path.resolve(__dirname, 'data-bak.txt')
// 读取文件的 stream 对象
const readStream = fs.createReadStream(fileName1)
// 写入文件的 stream 对象
const writeStream = fs.createWriteStream(fileName2)
// 通过 pipe执行拷贝,数据流转
readStream.pipe(writeStream)
// 数据读取完成监听,即拷贝完成
readStream.on('end', function () {console.log('拷贝完成')
}) 

一些打包工具的底层操作

目前一些比较火的前端打包构建工具,都是通过node.js编写的,打包和构建的过程肯定是文件频繁操作的过程,离不来stream,如gulp

最后

最近还整理一份JavaScript与ES的笔记,一共25个重要的知识点,对每个知识点都进行了讲解和分析。能帮你快速掌握JavaScript与ES的相关知识,提升工作效率。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

### Node.js 中的流(Stream)概念 在 Node.js 中,流是一种用于处理流式传输数据的对象。流可以被看作是一个可读、可写或两者兼有的对象,允许逐块而不是一次性加载整个文件到内存中[^1]。 #### 流的主要类型 Node.js 提供四种主要类型的流: - **Readable**:只提供读操作的数据源。 - **Writable**:只提供写入功能的目标。 - **Duplex**:既可以从其读也可以向其写的双向流。 - **Transform**:一种特殊的 Duplex 流,在其中可以通过某些转换函数修改数据。 这些流都实现了 EventEmitter 接口来触发事件通知监听器关于流状态的变化。 ```javascript const fs = require('fs'); // 创建一个可读流实例 let readableStream = fs.createReadStream('./example.txt', { encoding: 'utf8' }); readableStream.on('data', chunk => { console.log(`Received ${chunk.length} bytes of data.`); }); ``` 此代码片段展示了如何创建并监听来自文件系统的可读流上的 `data` 事件。每当有新的数据可用时就会调用回调函数,并打印接收到的数据量大小。 对于更复杂的场景,比如管道操作,则可以让多个流连接在一起形成流水线式的处理过程。例如将一个 HTTP 请求的内容直接传递给文件系统保存而不需要先缓存全部请求体再进行下一步动作。 ```javascript const http = require('http'); const fs = require('fs'); http.createServer((req, res) => { req.pipe(fs.createWriteStream('output.txt')); }).listen(8080); ``` 上述例子说明了一个简单的服务器设置,它接收客户端发送过来的信息并通过管道机制将其存储至本地磁盘上名为 output.txt 的文档内。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值