events
称为事件触发器,on()
用于注册监听器, emit()
用于触发事件。用例如下:
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('触发事件');
});
myEmitter.emit('event');
这就events
模块的使用,node中很多模块都继承于它,比如构建一个HTTP服务时处理post请求数据。
const http = require('http');
const server = http.createServer((req, res) => {
const buffers = [];
req.on('data', function (chunk) {
buffers.push(chunk);
});
req.on('end', function () {
const content = Buffer.concat(buffers).toString();
console.log(content)
});
})
server.listen(8080)
在处理post数据时通过on
注册了data
和end
事件,每当请求到来http模块内部会通过emit
触发这两个事件。
现在已经掌握了events模块的使用,下面介绍其实现原理。
const EventEmitter = {
_events = {
data: () => {},
end: () => {}
},
_eventsCount: 2,
}
events模块内部会维护一个这样的对象,_events
是保存事件名称和事件处理函数的对应关系,_eventsCount
是保存事件的个数。
第一步初始化这个对象
function EventEmitter() {
EventEmitter.init.call(this);
}
EventEmitter.init = function () {
if (this._events === undefined) {
this._events = Object.create(null);
this._eventsCount = 0;
}
}
第二步实现on
注册事件的方法
EventEmitter.prototype.addListener = function addListener(type, listener) {
return _addListener(this, type, listener)
}
function _addListener(target, type, listener) {
var events;
var existing;
checkListener(listener)
events = target._events;
if (events === undefined) {
events = target._events = Object.create(null);
target._eventsCount = 0;
} else {
existing = events[type]
}
if (existing === undefined) {
events[type] = listener;
++target._eventsCount;
} else {
if (typeof existing === 'function') {
existing = events[type] = [existing, listener]
} else {
existing.push(listener)
}
}
return target
}
EventEmitter.prototype.on = EventEmitter.prototype.addListener
第三步实现emit
触发事件的方法
EventEmitter.prototype.emit = function emit(type, ...args) {
const events = this._events;
const handler = events[type];
if (handler === undefined) {
return false
}
if (typeof handler === 'function') {
Reflect.apply(handler, this, args)
} else {
let len = handler.length;
const listeners = arrayClone(handler, len);
for (var i = 0; i < len; ++i) {
Reflect.apply(listeners[i], this, args)
}
}
}
function arrayClone(arr, n) {
var copy = new Array(n);
for (var i = 0; i < n; ++i) {
copy[i] = arr[i];
}
return copy;
}
现在已经基本完成了events的核心原理,其设计思想还是发布订阅。