实现从可读流到可写流的数据复制,也就是不断读->写的过程,那么你首先想到的是下面这个吗?代码看似简单,但是结果很糟糕,没有数据积压处理。如果读取的文件太大,结果会导致缓冲区数据溢出,程序会占用过多的系统内存,拖累服务器上的其他应用程序。不明白的可以看这篇文章Node.jsStreamBackpressure——消费端数据积压来不及处理会怎样?//坏例子,没有数据积压处理readable.on('data',data=>{writable.write(data)});和上面的需求类似,建议大家使用pipe()方法,以流拷贝的形式完成数据。作为学习,结合异步迭代器实现类似pipe的方法,以简单的方式完成从数据源到目标源的数据拷贝。写数据方法的目的是实现_write方法来控制可写流的数据写入。它返回一个Promise对象。如果可写流的dest.write()方法返回true,则表示内部缓冲区未满,继续写入。当dest.write()方法返回false时,意味着写入流的数据超过了它可以处理的最大容量限制。此时写入流的数据会被挂起,直到触发drain事件,表示buffer中的数据已经被drain完了。如果为空,可以继续写,然后将Promise对象变成解决方案。function_write(dest,chunk){returnnewPromise(resolve=>{if(dest.write(chunk)){returnresolve(null);}dest.once('drain',resolve);})}结合异步迭代器实现异步iteration设备更容易从可读流对象中读取数据,异步读取数据并调用我们封装的_write(chunk)方法写入数据,如果缓冲区空间已满,这里await_write(dest,chunk)也会等待,当缓冲区有空间继续写入时,再次读取->写入。函数myCopy(src,dest){returnnewPromise(async(resolve,reject)=>{dest.on('error',reject);try{forawait(constchunkofsrc){await_write(dest,chunk);}resolve();}catch(err){reject(err);}});}使用如下:constreadable=fs.createReadStream('text.txt');constwritable=fs.createWriteStream('dest-text.txt');awaitmyCopy(readable,可写);本文转载自微信公众号《Nodejs技术栈》,可通过以下二维码关注。转载本文请联系Nodejs技术栈公众号。
