0
点赞
收藏
分享

微信扫一扫

关于流操作的知识点【Node.js】

丹柯yx 2022-04-02 阅读 41
前端

目录

1、流是什么?

2、Node.js 为什么要用流?(传电影的例子)

3、node.js 是如何来使用流的呢?

4、可读流的实现

5、双工流的实现

6、结论


官网:Node.js Buffer(缓冲区) | 菜鸟教程

抽象的集合

  • 使用流操作数据可以简化代码
  • 使用流操作可以分段数据,配合管道设计的思想,可以自由加工和转换数据
  • 在它的内部实现了一个 Stream 模块,这个模块就是使用流操作处理数据的抽象接口集合
  • 在 node.js 中的流就像是一个工具包,它里面有很多小工具,不同的工具就对应着不同的数据操作
  • 在 Node.js 中就实现了四种类型的流操作: 可读流,可写流,双工流,转换流 
  • 最开始的时候 ,js 操作字符串
  • node平台下 js 操作二进制(buffer)
  • 在使用 buffer 去执行数据 IO 的时候很不方便,因此就产生了流操作
  • Node.js 里有一个模块叫 stream ,它里面实现了四个类( Readable Writable Duplex Transform )
    • 我们在使用的时候分为二种情况:
      •  一种就是 Node.js 内置的核心模块,它们本身就继承了流操作。(fs, net ,http, zlib)
      • 另外一种就是在学习流操作时常做的行为,自定义流 
// 模拟可读流的实现

let { Readable } = require('stream')

// 01.继承 Readable  类
// 02.重写它里面的 _read() 方法

class MyReadable extends Readable {
    constructor(source) {
        supper(source)
        // 当前我们正在模拟的操作是可读流,它其实就是一个能够产生数据的 “黑盒”
        // 因此这些一来我们就需要给它提供一些数据,用于模拟  底层数据 (磁盘上文件里的数据、程序中变量里的数据)
        this.source = source
    }
    _read() {
        // 将来我们从可读流里拿数据的时候,就按照要求调用 push 方法
        // 当 push  被调用的时候,就会自动的往缓冲区里添加一个数据,供使用者将来去获取
        // 而且 push 每执行一次,就意味着底层数据(source)中字节长度会少一些
        // 所以终有一天,底层数据是会被消耗干的,这个时候我们需要告知缓存区,没数据了
        // 此时只需要给 push 传入一个 null 值就可以了。
        let data = this.source.shift() || null 
        this.push(data)
    }
}

// 当前我利用一个数组存放数据来模拟底层数据
let source = ['zce', 'zcegg', 'syy']

// 01 可读流就是专门用于生产数据的流,我们也叫做数据源
// 02 在 pipe 管道设计中,可读流是处于 pipe 左侧的,也就是上游

let rs = new MyReadable (source)

// 03 请求,我闲着没事,造了一个可读流干吗?---》 如何来消费流当中的数据
// 数据的生产者,数据的消费者

// 04 对于 Readable 来说,它本身提供了二个事件用于我们消费数据。(data ,readable)

// 这里的 rs 居然能用 on 来订阅一个事件,就是因为 fs 模块不仅仅继承了 stream ,还继承了EventEmitter 类

rs.on('data', (chunk) => {
    console.log(chunk.toString())
})
// 可读就是生产数据, 可写就是消费数据, 双工就是既可读又可写  

let { Duplex } = require('stream')

class MyDuplex extends Duplex {
    constructor(source) {
        supper()
        this.source = source
    }
    _read() {
        let data = this.source.shift() || null
        this.push(data)
    }
    _write(chunk, en, cb) {
        // 可写流的操作就是在内部想办法把将来传进来数据 chunk 给消费掉
        // 此时我选择的就是将传递进来的 chunk 写到标准输出当中 
        process.stdout.write(chunk.toString().toUpperCase())
        // 当前的回调函数必须在 chunk 处理完成之后执行
        // 这个执行一定要发生在chunk处理完之后
        process.nextTick(cb)
    }
}

let source = ['a', 'b', 'c']

let ds = new MyDuplex(source)

ds.on('data', (chunk) => {
       console.log(chunk.toString())
})

// 只要是一个可写流,那就一定可以调用 write 方法

ds.write('aaa', 'utf-8', () => {
    console.log('再坚持一会,zce来接我')
})

  • 可读流就是生产数据
  • 可写流就是消费数据
  • 双工流可流可写 
  • 转换流本质上也是一个双工流,与 Duplex 不同的是它不仅仅可以实现读写操作,还可以在中间做自定义的数据转换,同时它的底层读写操作是打通的,这点 Duplex 是不具备的。
    • src().pipe(rename()) .pipe(min-css())... .dest('dist)  
  • gulp 里的插件都是用 Node写的,核心就是导出一个具备一定功能的转换流

举报

相关推荐

0 条评论