NodeJS——API使用之流

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/TDCQZD/article/details/82180225

一、流

stream(流)是一种在 Node.js 中处理流式数据的抽象接口。
基本上所有的流都继承了event接口。
Node.js 中有四种基本的流类型:

  • Readable - 可读取数据的流(例如 fs.createReadStream())。
  • Writable - 可写入数据的流(例如 fs.createWriteStream())。
  • Duplex - 可读又可写的流(例如 net.Socket)。
  • Transform - 在读写过程中可以修改或转换数据的 Duplex 流。

二、缓冲

可写流和可读流都会在一个内部的缓冲器中存储数据。缓存的数据量是有限的,会有一个阀门值。
1、可读流
当调用 stream.push(chunk) 时,数据会被缓冲在可读流中。 如果流的消费程序没有调用 stream.read(),则这些数据会停留在内部队列中,直到被消费。一旦内部的可读缓冲的总大小达到指定的阈值时。流会暂时停止从底层资源读取数据,直到当前缓冲的数据被消费。

怎么样算消费?

  • 调用 stream.read()
  • 新增一个 ‘data’ 事件处理函数。
  • 调用 stream.pipe() 方法发送数据到可写流。

2、可写流
当反复地调用 writable.write(chunk) 方法时,数据会被缓冲在可写流中。 当内部的可写缓冲的总大小小于设置的阈值时,调用 writable.write() 会返回 true。 一旦内部缓冲的大小达到或超过阈值时,则会返回 false。
3、使用问题
如果读写速度不一致,可能会导致爆仓!

三、Readable

1、两种模式
可读流实质上运作于流动中(flowing)或已暂停(paused)两种模式之一。

在 flowing 模式中,数据自动地从底层的系统被读取,并通过 EventEmitter 接口的事件尽可能快地被提供给应用程序。在 paused 模式中,必须显式调用 stream.read() 方法来从流中读取数据片段
2、模式切换
所有可读流都开始于 paused 模式,可以通过以下方式切换到 flowing 模式:

  • 新增一个 ‘data’ 事件处理函数。
  • 调用 stream.resume() 方法。
  • 调用 stream.pipe() 方法发送数据到可写流。

可读流可以通过以下方式切换回 paused 模式:

  • 如果没有管道目标,调用 stream.pause() 方法。
  • 如果有管道目标,移除所有管道目标。
  • 调用 stream.unpipe() 方法可以移除多个管道目标

3、相关事件
data
'data' 事件会在流将数据传递给消费者时触发
close
当流或其底层资源(比如文件描述符)被关闭时,触发 'close' 事件
end
'end' 事件将在流中再没有数据可供消费时触发
4、相关方法
push

readable.push(chunk[, encoding])
    chunk <Buffer> |  <string>  压入读队列的数据块
    encoding:编码

当可读流处在传输模式下,’data’事件触发时,可以通过 调用readable.read() 方法读出来数据,这数据是用readable.push()添加的
readable.read([size])
readable.read()方法从内部缓冲区中抽出并返回一些数据。 如果没有可读的数据,返回null。readable.read()方法默认数据将作为“Buffer”对象返回。

readable.read()方法只应该在暂停模式下的可读流上运行。
在流模式下,readable.read()自动调用直到内部缓冲区的数据完全耗尽。
readable.pause()
readable.pause() 方法将会使 flowing 模式的流停止触发 ‘data’ 事件, 进而切出 flowing 模式。任何可用的数据都将保存在内部缓存中。
readable.resume()
readable.resume() 方法会重新触发 ‘data’ 事件, 将暂停模式切换到流动模式。
readable.pipe(destination)

destination <stream.Writable> 数据写入目标

readable.pipe() 绑定一个 Writable 到 readable 上, 将可写流自动切换到 flowing 模式并将所有数据传给绑定的 Writable。数据流将被自动管理。这样,即使是可读流较快,目标可写流也不会超负荷(overwhelmed)

四、 Writable

1、 HTTP
参考NodeJs内置模块之HTTP模块
2、相关事件
close
当流或其底层资源(比如文件描述符)被关闭时,触发 ‘close’ 事件。
drain
如果调用 stream.write(chunk) 方法返回 false,则在适合恢复写入数据到流时触发 ‘drain’ 事件。
finish
调用 stream.end() 方法且缓冲数据都已经传给底层系统之后,触发 ‘finish’ 事件。
3、相关方法
writable.write(chunk[, encoding][, callback])
writable.write() 方法写入一些数据到流中,并在这些数据被完全处理之后调用提供的 callback。
参数说明:

  • chunk: 要写入的数据,String 或 Buffer。
  • encoding : 如果 chunk 是字符串,则指定字符编码。
  • callback: 当这块数据被输出时的回调函数。

writable.end([chunk][, encoding][, callback])
调用 writable.end() 方法表明已没有数据要被写入可写流。
可选的 chunk 和 encoding 参数可以在关闭流之前立即再写入一块数据。 如果传入了可选的 callback 函数,则它会做为监听器被添加到 ‘finish’ 事件。
调用 stream.end() 之后再调用 stream.write() 方法会导致错误。

五、代码示例:

01_流_基本使用.js

const fs = require("fs")
const  readStream = fs.createReadStream("./test.mp4")
const  writeStream = fs.createWriteStream("./test2.mp4")

readStream.on("data",(data)=>{
    writeStream.write(data)
})

readStream.on("end",()=>{
   writeStream.end()
})

02_流_优化(防缓冲流爆仓).js

const fs = require("fs")
const  readStream =fs.createReadStream("./test.mp4")
const  writeStream =fs.createWriteStream("./test2.mp4")

readStream.on("data",(data)=>{
    const  flag = writeStream.write(data)
    if (!flag){
        readStream.pause()
    }
})

readStream.on("end",()=>{
   writeStream.end()
})

writeStream.on("drain",()=>{
    readStream.resume()
})

03_流_优化(管道).js

const fs = require("fs")
const  readStream =fs.createReadStream("./test.mp4")
const  writeStream =fs.createWriteStream("./test2.mp4")

readStream.pipe(writeStream)

猜你喜欢

转载自blog.csdn.net/TDCQZD/article/details/82180225