浅析Node.js 中 Stream API 的使用_node.js
本文由浅入深给大家介绍node.js stream api,具体详情请看下文吧。
基本介绍
在 Node.js 中,读取文件的方式有两种,一种是用 fs.readFile ,另外一种是利用 fs.createReadStream 来读取。
fs.readFile 对于每个 Node.js 使用者来说最熟悉不过了,简单易懂,很好上手。但它的缺点是会先将数据全部读入内存,一旦遇到大文件的时候,这种方式读取的效率就非常低下了。
而 fs.createReadStream 则是通过 Stream 来读取数据,它会把文件(数据)分割成小块,然后触发一些特定的事件,我们可以监听这些事件,编写特定的处理函数。这种方式相对上面来说,并不好上手,但它效率非常高。
事实上, Stream 在 Node.js 中并非仅仅用在文件处理上,其他地方也可以看到它的身影,如 process.stdin/stdout , http , tcp sockets , zlib , crypto 等都有用到。
本文是我学习 Node.js 中的 Stream API 中的一点总结,希望对大家有用。
特点
基于事件通讯
可以通过 pipe 来连接流
种类
Readable Stream 可读数据流
Writeable Stream 可写数据流
Duplex Stream 双向数据流,可以同时读和写
Transform Stream 转换数据流,可读可写,同时可以转换(处理)数据
事件
可读数据流的事件
readable 数据向外流时触发
data 对于那些没有显式暂停的数据流,添加data事件监听函数,会将数据流切换到流动态,尽快向外提供数据
end 读取完数据时触发。注意不能和 writeableStream.end() 混淆,writeableStream 并没有 end 事件,只有 .end() 方法
close 数据源关闭时触发
error 读取数据发生错误时触发
可写数据流的事件
drain writable.write(chunk) 返回 false 之后,缓存全部写入完成,可以重新写入时就会触发
finish 调用 .end 方法时,所有缓存的数据释放后触发,类似于可读数据流中的 end 事件,表示写入过程结束
pipe 作为 pipe 目标时触发
unpipe 作为 unpipe 目标时触发
error 写入数据发生错误时触发
状态
可读数据流有两种状态: 流动态 和 暂停态 ,改变数据流状态的方法如下:
暂停态 -> 流动态
添加 data 事件的监听函数
调用 resume 方法
调用 pipe 方法
注意:如果转为流动态时,没有 data 事件的监听函数,也没有 pipe 方法的目的地,那么数据将遗失。
流动态 -> 暂停态
不存在 pipe 方法的目的地时,调用 pause 方法
存在 pipe 方法的目的地时,移除所有 data 事件的监听函数,并且调用 unpipe 方法,移除所有 pipe 方法的目的地
注意:只移除 data 事件的监听函数,并不会自动引发数据流进入「暂停态」。另外,存在 pipe 方法的目的地时,调用 pause 方法,并不能保证数据流总是处于暂停态,一旦那些目的地发出数据请求,数据流有可能会继续提供数据。
用法
读写文件
var fs = require('fs'); // 新建可读数据流 var rs = fs.createReadStream('./test1.txt'); // 新建可写数据流 var ws = fs.createWriteStream('./test2.txt'); // 监听可读数据流结束事件 rs.on('end', function() { console.log('read text1.txt successfully!'); }); // 监听可写数据流结束事件 ws.on('finish', function() { console.log('write text2.txt successfully!'); }); // 把可读数据流转换成流动态,流进可写数据流中 rs.pipe(ws); 读取 CSV 文件,并上传数据(我在生产环境中写过) var fs = require('fs'); var es = require('event-stream'); var csv = require('csv'); var parser = csv.parse(); var transformer = csv.transform(function(record) { return record.join(','); }); var data = fs.createReadStream('./demo.csv'); data .pipe(parser) .pipe(transformer) // 处理前一个 stream 传递过来的数据 .pipe(es.map(function(data, callback) { upload(data, function(err) { callback(err); }); })) // 相当于监听前一个 stream 的 end 事件 .pipe(es.wait(function(err, body) { process.stdout.write('done!'); }));
更多用法
可以参考一下 https://github.com/jeresig/node-stream-playground ,进去示例网站之后直接点 add stream 就能看到结果了。
常见坑
用 rs.pipe(ws) 的方式来写文件并不是把 rs 的内容 append 到 ws 后面,而是直接用 rs 的内容覆盖 ws 原有的内容
已结束/关闭的流不能重复使用,必须重新创建数据流
pipe 方法返回的是目标数据流,如 a.pipe(b) 返回的是 b,因此监听事件的时候请注意你监听的对象是否正确
如果你要监听多个数据流,同时你又使用了 pipe 方法来串联数据流的话,你就要写成:
data
.on('end', function() { console.log('data end'); }) .pipe(a) .on('end', function() { console.log('a end'); }) .pipe(b) .on('end', function() { console.log('b end'); });
常用类库
event-stream 用起来有函数式编程的感觉,个人比较喜欢
awesome-nodejs#streams 由于其他 stream 库我都没用过,所以有需求的就直接看这里吧
以上内容是小编给大家介绍的Node.js 中 Stream API 的使用,希望大家喜欢。

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

Python和JavaScript开发者的薪资没有绝对的高低,具体取决于技能和行业需求。1.Python在数据科学和机器学习领域可能薪资更高。2.JavaScript在前端和全栈开发中需求大,薪资也可观。3.影响因素包括经验、地理位置、公司规模和特定技能。

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

如何在JavaScript中将具有相同ID的数组元素合并到一个对象中?在处理数据时,我们常常会遇到需要将具有相同ID�...

深入探讨console.log输出差异的根源本文将分析一段代码中console.log函数输出结果的差异,并解释其背后的原因。�...

实现视差滚动和元素动画效果的探讨本文将探讨如何实现类似资生堂官网(https://www.shiseido.co.jp/sb/wonderland/)中�...

学习JavaScript不难,但有挑战。1)理解基础概念如变量、数据类型、函数等。2)掌握异步编程,通过事件循环实现。3)使用DOM操作和Promise处理异步请求。4)避免常见错误,使用调试技巧。5)优化性能,遵循最佳实践。

探索前端中类似VSCode的面板拖拽调整功能的实现在前端开发中,如何实现类似于VSCode...
