Readable Stream

静止态paused和流动态flowing

可读的流是可以停止的,就是读着读着就突然不给你数据了(没办法继续读了)。
可读的流可以理解为是一个内容的生产者,当它不发内容了,他就处于一个静止的状态。当他又开始发内容了,他就处于一个流动态。

  • 默认处于paused态

比如你去读一个文件,你不去pipe,不去监听(就是把下面红框的代码删掉),那么你读取了的文件的内容流向何处呢? 没有地方可以去,所以是静止态的。
image.png

  • 添加data事件监听,他就变为flowing态

当你添加了pipe等事件之后,他就会开始流动了。
pipe是一个监听事件。pipe就是监听第一个流的data事件,然后把数据写到第二个流。

  • 删掉data事件监听,他就变为paused态

也可以主动地改变流的状态

  • pause() 可以将它变为paused

当处于paused的时候,用户就拿不到big_file.txt的数据了。

  • resume() 可以将它变为flowing

Writable Stream

drain

drain 流干了事件,表示可以加点水了

背景

之前的文章:stream对象的原型、事件有详细说过https://www.yuque.com/u640022/lgv5t2/km8vrm

  • 当我们调用stream.write(chunk)的时候,可能会得到false
  • false的意思是 你写得太快了,数据积压了
  • 这个时候我们不能在write了,要监听drain
  • 等drain事件触发了,我们才能继续write

官方文档 有例子http://nodejs.cn/api/stream.html#stream_event_drain

改写这个例子

  1. const fs = require('fs')
  2. function writeOneMillionTimes(writer, data) {
  3. let i = 1000000
  4. write()
  5. function write() {
  6. let ok = true
  7. do {
  8. i--
  9. if (i === 0) {
  10. // Last time!
  11. writer.write(data)
  12. } else {
  13. // See if we should continue, or wait.
  14. // Don't pass the callback, because we're not done yet.
  15. ok = writer.write(data)
  16. if (ok === false) {
  17. console.log('不能再写了')
  18. }
  19. }
  20. } while (i > 0 && ok)
  21. if (i > 0) {
  22. // Had to stop early!
  23. // Write some more once it drains.
  24. writer.once('drain', () => {
  25. console.log('干涸了')
  26. write()
  27. })
  28. }
  29. }
  30. }
  31. const writer = fs.createWriteStream('./big_file.txt')
  32. writeOneMillionTimes(writer, 'hello world'

运行这个文件
image.png
就会不断的干涸,堵车。

finsh事件

触发finish事件需要两个条件

  1. 调用stream.end()之后,而且
  2. 缓冲区数据都已经传给底层系统之后 才触发finish

缓冲区的数据是什么:
当我们往文件写东西的时候,并不是直接写到文件里,或者说文件不是直接存到硬盘,而是有一个缓冲,到了一定程度之后才会写到硬盘(保存文件)