聊一聊node的流

1.Node.js中Stream 有四种流类型:

  • Readable - 可读操作。
  • Writable - 可写操作。
  • Duplex - 可读可写操作.
  • Transform - 操作被写入数据,然后读出结果。
    概念:Stream 是一个抽象接口,Node 中有很多对象实现了这个接口。例如,对http 服务器发起请求的request 对象就是一个 Stream,还有stdout(标准输出)

2.所有的 Stream 对象都是 EventEmitter 的实例。常用的事件有:

  • data - 当有数据可读时触发。
  • end - 没有更多的数据可读时触发。
  • error - 在接收和写入过程中发生错误时触发。
  • finish - 所有数据已被写入到底层系统时触发。

3.可读流

A.可读流有两种模式
1、流动模式:可读流自动读取数据,通过EventEmitter接口的事件尽快将数据提供给应用。
2、暂停模式:必须显式调用stream.read()方法来从流中读取数据片段。
复制代码
B.暂停模式切换到流动模式的api有:
1、监听“data”事件
2、调用 stream.resume()方法
3、调用 stream.pipe()方法将数据发送到可写流。
复制代码

C.流动模式切换到暂停模式的api有:

1、如果不存在管道目标,调用stream.pause()方法
2、如果存在管道目标,调用 stream.unpipe()并取消'data'事件监听
复制代码

D.创建可读流

const fs = require('fs');   // 引入fs核心模块

// fs.createReadStream(path, options)
// 返回的是一个可读流对象
let rs = fs.createReadStream('1.txt', {
    flags: 'r',         // 文件的读取操作,默认是'r':读取
    encoding: 'utf8',   // 设置编码格式,默认是null, null代表的是buffer
    autoClose: true,    // 读取完毕后自动关闭
    highWaterMark: 3,   // 默认是读取64k    64 * 1024字节
    start: 0,
    end: 3              // 文件结束位置索引,和正常的截取slice有所不同,包前又包后(包括自己结束的位置)
});

// 默认情况下,不会将文件中的内容输出
// 内部会先创建一个buffer先读取3字节

// 1.txt文件内容为 123456789
-----
rs.on('data', data => { // 非流动模式 -> 流动模式
    console.log(data);  // 触发2次data事件, 分别打出123和4  从0到3共4个(包括末尾)
});
----
rs.on('end', function () {
    console.log('读取完成');
});
----
通过pause()方法和resume()方法暂停和恢复触发data
rs.on('data', function (data) {
    rs.pause();
    console.log(data);
});
setTimeout(function () {
    rs.resume();
},2000);
复制代码

4.可写流

1、监听‘readable’事件,这时可读流会读取64k(可以在创建可读流时,通过option参数中的highWaterMark更改)数据到流的缓存区中,等待你用read方法去读取并消费数据,当你用read方法读了64k数据之后,会再次触发readable事件,直到你读完了源文件的所有数据。
    2、如果你选择监听‘data’事件,流切换到流动模式,数据会被尽可能快的读出
    3.接下来,不论我们以哪种方式读到了文件中的数据,这时我们都可以创建一个可写流并调用可写流的write方法来消费读到的数据。调用write方法会向文件中写入数据,但是因为写入的速度较慢,如果当前写入还在进行,而你又调用了write方法,node会将你要写入的数据缓存在一个缓存区中,等到文件写入完毕会从缓存区中取出数据,继续写入。     write方法拥有一个布尔类型的返回值,用来表示目前是否还可以继续调用write方法写入内容。如果返回false,我们应当停止读取数据以避免消耗过多内存。那么什么时候会返false呢?就是当缓存区的大小大于16k(可以在创建可读流时,通过option参数中的highWaterMark更改)时。     缓存区满后,文件写入一直在进行,不一会儿会把缓存区的内容全部写入,缓存区处于清空状态,这时会触发可写流的‘drain’事件,这时我们可以继续向文件写入数据了。注意:如果缓存区从未满过,‘drain’事件永远也不会触发。

let fs = require('fs');
//创建可读可写流
let rs = fs.createReadStream('./1.txt');
let ws = fs.createWriteStream('./2.txt');
//监听‘data’事件,开启流动模式
rs.on('data',function (data) {
    //对应图中的可写流truefalse
    let flag = ws.write(data);
    if(!flag){
        //如果可写流返回false,我们应当停止读取,以避免消耗过多内存
        rs.pause();
    }
});
//对应图中的drain事件
ws.on('drain',function () {
    //重新开启流动模式
    rs.resume();
});

//使用可读流的暂停模式
function read() {
    let data = rs.read()
    let flag = ws.write(data);
    if(flag){
       read()
    }
}
rs.on('readable',function(){
    read()
})

ws.on('drain',function () {
    read()
});
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值