Stream对象的原型链
如何查看Stream对象的原型链
调试
文件:4.js
const fs = require('fs')
const s = fs.createReadStream('./big_file.txt')
console.log(s)
命令行:输入 node —inspect-brk 4.js
打开浏览器:随便一个网页 F12 打开调试工具
看到node的图标 点击打开它
就可以看到刚刚的4.js文件了。 点击就可以打断点了
记住要打断点才可以查看到s的log。 因为不断点的话,运行完之后nodejs就会退出,看不到详细的s的属性。
现在我们可以从上图的proto:Readable查看它的继承属性了
可以看到Writable上的重要属性跟方法:close() 和 open()
而且可以看到Readable继承自Stream
可以看到stream上的重要方法
stream.on() 这个方法使得我们可以监听stream的data和end等事件
还有常用的pipe,read等方法
Stream对象的原型链解析
s = fs.createReadStream(path)
- 那么它的对象层级为:
- 自身属性(由fs.createReadStream 构造)
- 原型:stream.Readable.prototype
- 二级原型:stream.Stream.prototype
- 三级原型:events.EventEmitter.prototype
- EventEmitter一般是一些事件的api 比如on之类的
- 四级原型:Object.prototype
所有的Stream对象都继承了EventEmitter
所以stream对象都可以发出事件,以及可以去监听这个事件
stream支持的事件与方法
重点说下 drain
drain的作用是什么呢:
数据写太慢或者写太快都会出现一些异常
比如在一个高速传输数据的流里,在管道口堵车了,该怎么办
堵车了怎么办呢
- 需要知道到底有没有堵
stream.wirte()会返回一个布尔值,如果是true 就表示没有堵车,可以继续写。如果是false,就说明堵车了,不能写了。
- 什么时候不堵了,可以通车了
就是通过stream.on(‘drain’,()=>{})去监听,这个事件的意思是:数据流干了,车都走完了,那后面的车就可以继续走了,数据就继续写。
我们可以用回上一章 管道的例子进行改写:
//stream1一有数据就塞给stream2
stream1.on('data',(chunk)=>{
const flag = stream2.write(chunk)
if(flag === false){
dont write
}
stream.on('drain',()=>{
go on write
})
})
//stream1停了,就停掉stream2
stream1.on('end',()=>{
stream2.end()
})
这样 我们就可以使用stream.on(‘drain’,()=>{}) 去得以知道,已经不堵车了,继续传输数据。
就是管道口的数据已经流干了。
所以这个事件是在我们处理比较高速的数据或者低速的数据流才会用到的,这个问题会引发很多后续的问题,需要继续去研究。
finish
finsh也是写完了的意思
跟drain的区别是:
finsh是整个都写完了
drain是这一部分写完了
cork
writable.cork()
方法强制把所有写入的数据都缓冲到内存中。 当调用 stream.uncork()
或 stream.end()
方法时,缓冲的数据才会被输出
文档:http://nodejs.cn/api/stream.html#stream_writable_cork