一、EventEmitter
构造与添加监听器
该对象由node的event模块提供,扩展它可以获得一个EventEmitter类,实例化后即可添加监听器
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('an event occurred!');
});
myEmitter.emit('event');
触发事件在最后一行,使用emit方法即可。
在事件处理器中(若是常规事件被调用),this默认指向事件绑定的EventEmitter,但如果使用了箭头函数,因为它遵循词法作用域,this将会指向一个空对象。
异步与同步
EventEmitter在默认情况下会同步执行所有的监听器,若想采用异步模式,使用setImmediate()或process.nextTick()方法
其他支持的功能
- 监听器可以被调用多次,也可以只被调用一次,例如once()接口
- EventEmitter绑定和销毁监听器时会对应地触发newListener和removeListener事件
- 此外还有对监听器数量、名称、上限等作操作的各种接口,详情参见node.js官方文档
二、Stream
分类
- Stream包括Readable Stream, Writable Stream, Duplex Stream和Transform Stream,前两种顾名思义,第三种指代既可读又可写的流,第四种则是可以修改或转换的Duplex Stream
- 对象模式:流在默认情况下以Buffer, String或Uint8Array形式传输,但可以通过objectMode参数修改为对象模式,对象模式接受除null以外的其他数据类型
缓存及其意义
缓存容量由highWaterMark标识,避免内存压力过大,同时读和写有各自的缓存区,保证在速度有所差别的情况下,它们能各自独立工作。
可写流
- HTTP requests, on the client
- HTTP responses, on the server
- fs write streams
- zlib streams
- crypto streams
- TCP sockets
- child process stdin
- process.stdout, process.stderr
Writable类实现了多个控制读操作的方法,举drain方法为例,它在重新允许将数据写入流时触发(Writable.write()返回值即将由false变为true):
function writeOneMillionTimes(writer, data, encoding, callback) {
let i = 1000000;
write();
function write() {
let ok = true;
do {
i--;
if (i === 0) {
// last time!
writer.write(data, encoding, callback);
} else {
// see if we should continue, or wait
// don't pass the callback, because we're not done yet.
ok = writer.write(data, encoding);
}
} while (i > 0 && ok);
if (i > 0) {
// had to stop early!
// write some more once it drains
writer.once('drain', write);
}
}
}
这段官方demo大约是做了这么一件事:将data写出一百万次,若是正常结束就执行callback回调,若是被迫中止(back pressure),则触发drain事件~
此外还有cork将写入的数据由缓存全部存入内存,直到调用Writable.uncork()时被重新激活
可读流
其包含的流类型与可写流类似,需要讨论的是它的两种模式,三个状态~
两种模式:包含flowing和paused,flow模式下,通过EventEmitter发布的data事件,数据将自动进行读写,速度快;paused模式下,需要显式地调用stream.read()方法来指定读取的数据块。
三个状态:指的是readable._readableState.flowing的状态,初始为null,没有消费者,因此数据也不会生成,但当模式变为flowing后它的值也会切换为true,启动生成数据-发布data事件的流程。
node.js的其余部分之后再写~