node里的stream-搬砖备忘

99 阅读2分钟

继承关系

classDiagram
EventEmitter <|-- Stream
Stream <|-- Readable
Stream <|-- Writable
Readable <|-- Duplex
Writable <|-- Duplex
Duplex <|-- Transform
Transform <|-- PassThrough

流都是可以被继承的

  • 继承Readable 复写_read 只要有on data监听,流还有数据,就不断自调用(不断读,内部记录了每次读的大小,当前应读哪个位置到哪个位置)-------经常可读流会被调一个this.push意思就是往可读流的缓冲区放数据

  • 继承Writable 复写_write, 外部调用写数据会传个回调。内部不断往缓冲区放,每次放都检查缓冲区是否满了,满了就真实的写(利用回调做连锁写入),内部也是维护了上次写到哪儿了。本次写多少进去。

  • 读写都是往缓冲区,释放数据Readable是on或者pipe(其实就是on),Writable就是flush之类的,具体参考文档

  • 继承duplex自然是复写_read & 复写_write

  • Transform复写多了一个_transform, 在别人调_write会调_transform,自动把传入next的数据放入自己的可读流里,也就是this.push

function Transform(options) {
    Duplex.call(this, options); 
    if (options.transform) this._transform = options.transform; 
} 

Transform.prototype._write = function (chunk, encoding, next) { 
    this._transform(chunk, encoding, (err, data) => { 
    if (data) { 
        this.push(data); 
     } 
     next(err); 
     }); 
}
  • through就是Transform,没啥区别

流都有对象模式,objectMode: true,读出来的write进去的,就都是每次写入、读出的对象

  • 常见用法
  • read.pipe(write).write
  • read.pipe(transform).write
source: pipe(param): read.on('data', () => {
    param._write()   
})

glob

  • glob能match出跟这类形式字符串匹配的所有的文件"src/**/*.xxx", glob-parent to-absolute-glob可以获取基于"src/**/*.xxx"的绝对路径,父目录。
  • 这里有个稀奇的点如果一个数据源数据量庞大,需要切分不断传给某个类对象,就可以让那个类继承可读流,然后收到数据不断this.push, 那么它的对象就可以通过on data不断拿数据。

vinyl

  • 虚拟文件对象,就是一个JS对象,用来描述一个文件的
  • 对象里的content要么是buffer,要么是stream