stream模式不能接受blob文件_Node开发进阶:彻底理解Stream

作为一个Node开发者,今天整理了一篇关于流的文章,跟大伙一起分享

f198facef0d24fe19c113550f8529d33.png

1. 流的概念

  • 流是一组有序的,有起点和终点的字节数据传输手段
  • 它不关心文件的整体内容,只关注是否从文件中读到了数据,以及读到数据之后的处理
  • 流是一个抽象接口,被 Node 中的很多对象所实现。比如HTTP 服务器request和response对象都是流。

2.可读流createReadStream

实现了stream.Readable接口的对象,将对象数据读取为流数据,当监听data事件后,开始发射数据

fs.createReadStream = function(path, options) { return new ReadStream(path, options);};

2.1 创建可读流

var rs = fs.createReadStream(path,[options]);
  1. path读取文件的路径
  2. options
  • flags打开文件要做的操作,默认为'r'
  • encoding默认为null
  • start开始读取的索引位置
  • end结束读取的索引位置(包括结束位置)
  • highWaterMark读取缓存区默认的大小64kb

注意:如果指定utf8编码highWaterMark要大于3个字节

2.2 监听data事件

流切换到流动模式,数据会被尽可能快的读出

rs.on('data', function (data) { console.log(data);});

2.3 监听end事件

该事件会在读完数据后被触发

rs.on('end', function () { console.log('读取完成');});

2.4 监听error事件

该事件会在读完数据出错时被触发

rs.on('error', function (err) { console.log(err);});

2.5 监听open事件

该事件会在打开被读取文件时被触发

rs.on('open', function () { console.log(err);});

2.6 监听close事件

该事件会在关闭被读取文件时被触发

rs.on('close', function () { console.log(err);});

2.7 设置编码

与指定{encoding:'utf8'}效果相同,设置编码

rs.setEncoding('utf8');

2.8 暂停和恢复触发data

通过pause()方法和resume()方法

rs.on('data', function (data) { rs.pause(); console.log(data);});setTimeout(function () { rs.resume();},2000);

3.可写流createWriteStream

实现了stream.Writable接口的对象来将流数据写入到对象中

fs.createWriteStream = function(path, options) { return new WriteStream(path, options);};

3.1 创建可写流

var ws = fs.createWriteStream(path,[options]);
  1. path写入的文件路径
  2. options
  • flags打开文件要做的操作,默认为'w'
  • encoding默认为utf8
  • highWaterMark写入缓存区的默认大小16kb

3.2 write方法

ws.write(chunk,[encoding],[callback]);
  1. chunk写入的数据buffer/string
  2. encoding编码格式chunk为字符串时有用,可选
  3. callback 写入成功后的回调

注意:返回值为布尔值,系统缓存区满时为false,未满时为true

3.3 end方法

ws.end(chunk,[encoding],[callback]);

表明接下来没有数据要被写入 Writable 通过传入可选的 chunk 和 encoding 参数,可以在关闭流之前再写入一段数据 如果传入了可选的 callback 函数,它将作为 'finish' 事件的回调函数

3.4 drain方法

  • 当一个流不处在 drain 的状态, 对 write() 的调用会缓存数据块, 并且返回 false。 一旦所有当前所有缓存的数据块都排空了(被操作系统接受来进行输出), 那么 'drain' 事件就会被触发
  • 建议, 一旦 write() 返回 false, 在 'drain' 事件触发前, 不能写入任何数据块
let fs = require('fs');let ws = fs.createWriteStream('./2.txt',{ flags:'w', encoding:'utf8', highWaterMark:3});let i = 10;function write(){ let flag = true; while(i&&flag){ flag = ws.write("1"); i--; console.log(flag); }}write();ws.on('drain',()=>{ console.log("drain"); write();});

3.5 finish方法

在调用了 stream.end() 方法,且缓冲区数据都已经传给底层系统之后, 'finish' 事件将被触发。

var writer = fs.createWriteStream('./2.txt');for (let i = 0; i < 100; i++) { writer.write(`hello, ${i}!`);}writer.end('结束');writer.on('finish', () => { console.error('所有的写入已经完成!');});

4.pipe方法

4.1 pipe方法的原理

var fs = require('fs');var ws = fs.createWriteStream('./2.txt');var rs = fs.createReadStream('./1.txt');rs.on('data', function (data) { var flag = ws.write(data); if(!flag) rs.pause();});ws.on('drain', function () { rs.resume();});rs.on('end', function () { ws.end();});

4.2 pipe用法

readStream.pipe(writeStream);var from = fs.createReadStream('./1.txt');var to = fs.createWriteStream('./2.txt');from.pipe(to);

将数据的滞留量限制到一个可接受的水平,以使得不同速度的来源和目标不会淹没可用内存。

4.3 unpipe用法

  • readable.unpipe()方法将之前通过stream.pipe()方法绑定的流分离
  • 如果 destination 没有传入, 则所有绑定的流都会被分离.
let fs = require('fs');var from = fs.createReadStream('./1.txt');var to = fs.createWriteStream('./2.txt');from.pipe(to);setTimeout(() => {console.log('关闭向2.txt的写入');from.unpipe(writable);console.log('手工关闭文件流');to.end();}, 1000);

4.4 cork

调用 writable.cork() 方法将强制所有写入数据都存放到内存中的缓冲区里。 直到调用 stream.uncork() 或 stream.end() 方法时,缓冲区里的数据才会被输出。

4.5 uncork

writable.uncork()将输出在stream.cork()方法被调用之后缓冲在内存中的所有数据。

stream.cork();stream.write('1');stream.write('2');process.nextTick(() => stream.uncork());

5. 简单实现

5.1 可读流的简单实现

代码较多,直接上图:

85b206cf5818fd0d972c2ffeb2e461b1.png

5.2 可写流的简单实现

代码较多,直接上图:

bb53339a857756e66790692ad16ae8a8.png

5.3 pipe的简单实现

代码较多,直接上图:

a46aa9dcfda1e5ab90d43b5c7ae1b3e3.png

5.4 可读流暂停模式实现

代码较多,直接上图:

3005ada4f47342d9dd2c3fa52b00ba82.png

小结

这篇文章的东西不算复杂,但需要大伙多看多写,多理解。这样才能在开发这条路上走的更远。最后也谢谢大伙的支持。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值