Node.js中大部分的模块,都继承自Event模块(也就是events.EventEmitter)是一个简单的事件监听器模式的实现
关于events.EventEmitter的使用
在下面这段代码中,通过EventEmitter 类的实例来绑定和监听事件
var events = require('events');
var eventEmitter = new events.EventEmitter();
var connectHandle = function connected(){
console.log('连接成功');
eventEmitter.emit('data_received');
}
eventEmitter.on('connection', connectHandle);
eventEmitter.on('data_received', function(){
console.log('数据接收成功');
});
eventEmitter.emit('connection');
console.log('程序执行结束');
console.log(require('events').EventEmitter.listenerCount(eventEmitter, 'connection'));
运行结果如下:
EventEmitter 实例的本质就是一个和事件有关系的对象
这里我写的consoleobjectContent函数就是为了输出EventEmitter 实例里面的具体内容
function consoleobjectContent(obj){
for(var i in obj){
if (typeof obj[i] === 'object') {
consoleobjectContent(obj[i]);
}else{
console.log(i + obj[i]);
console.log('---------------------');
}
}
}
调用如下:
consoleobjectContent(eventEmitter);
运行结果如下:
connection: function connected(){
console.log(‘连接成功’);
eventEmitter.emit(‘data_received’);
}
data_received: function (){
console.log(‘数据接收成功’);
}
_eventsCount: 2
_maxListeners: undefined
setMaxListeners: function setMaxListeners(n) {
if (typeof n !== ‘number’ || n < 0 || isNaN(n))
throw new TypeError(‘“n” argument must be a positive number’);
this._maxListeners = n;
return this;
}
getMaxListeners: function getMaxListeners() {
return $getMaxListeners(this);
}
emit: function emit(type) {
var er, handler, len, args, i, events, domain;
var needDomainExit = false;
var doError = (type === ‘error’);
events = this._events;
if (events)
doError = (doError && events.error == null);
else if (!doError)
return false;
domain = this.domain;
// If there is no ‘error’ event listener then throw.
if (doError) {
er = arguments[1];
if (domain) {
if (!er)
er = new Error(‘Uncaught, unspecified “error” event’);
er.domainEmitter = this;
er.domain = domain;
er.domainThrown = false;
domain.emit(‘error’, er);
} else if (er instanceof Error) {
throw er; // Unhandled ‘error’ event
} else {
// At least give some kind of context to the user
var err = new Error(‘Uncaught, unspecified “error” event. (’ + er + ‘)’);
err.context = er;
throw err;
}
return false;
}
handler = events[type];
if (!handler)
return false;
if (domain && this !== process) {
domain.enter();
needDomainExit = true;
}
var isFn = typeof handler === ‘function’;
len = arguments.length;
switch (len) {
// fast cases
case 1:
emitNone(handler, isFn, this);
break;
case 2:
emitOne(handler, isFn, this, arguments[1]);
break;
case 3:
emitTwo(handler, isFn, this, arguments[1], arguments[2]);
break;
case 4:
emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]);
break;
// slower
default:
args = new Array(len - 1);
for (i = 1; i < len; i++)
args[i - 1] = arguments[i];
emitMany(handler, isFn, this, args);
}
if (needDomainExit)
domain.exit();
return true;
}
addListener: function addListener(type, listener) {
return _addListener(this, type, listener, false);
}
on: function addListener(type, listener) {
return _addListener(this, type, listener, false);
}
prependListener: function prependListener(type, listener) {
return _addListener(this, type, listener, true);
}
once: function once(type, listener) {
if (typeof listener !== ‘function’)
throw new TypeError(‘“listener” argument must be a function’);
this.on(type, _onceWrap(this, type, listener));
return this;
}
prependOnceListener: function prependOnceListener(type, listener) {
if (typeof listener !== ‘function’)
throw new TypeError(‘“listener” argument must be a function’);
this.prependListener(type, _onceWrap(this, type, listener));
return this;
}
removeListener: function removeListener(type, listener) {
var list, events, position, i, originalListener;
if (typeof listener !== 'function')
throw new TypeError('"listener" argument must be a function');
events = this._events;
if (!events)
return this;
list = events[type];
if (!list)
return this;
if (list === listener || (list.listener && list.listener === listener)) {
if (--this._eventsCount === 0)
this._events = new EventHandlers();
else {
delete events[type];
if (events.removeListener)
this.emit('removeListener', type, list.listener || listener);
}
} else if (typeof list !== 'function') {
position = -1;
for (i = list.length; i-- > 0;) {
if (list[i] === listener ||
(list[i].listener && list[i].listener === listener)) {
originalListener = list[i].listener;
position = i;
break;
}
}
if (position < 0)
return this;
if (list.length === 1) {
list[0] = undefined;
if (--this._eventsCount === 0) {
this._events = new EventHandlers();
return this;
} else {
delete events[type];
}
} else {
spliceOne(list, position);
}
if (events.removeListener)
this.emit('removeListener', type, originalListener || listener);
}
return this;
}
removeAllListeners: function removeAllListeners(type) {
var listeners, events;
events = this._events;
if (!events)
return this;
// not listening for removeListener, no need to emit
if (!events.removeListener) {
if (arguments.length === 0) {
this._events = new EventHandlers();
this._eventsCount = 0;
} else if (events[type]) {
if (--this._eventsCount === 0)
this._events = new EventHandlers();
else
delete events[type];
}
return this;
}
//emit removeListener for all listeners on all events
if (arguments.length === 0) {
var keys = Object.keys(events);
for (var i = 0, key; i < keys.length; ++i) {
key = keys[i];
if (key === 'removeListener') continue;
this.removeAllListeners(key);
}
this.removeAllListeners('removeListener');
this._events = new EventHandlers();
this._eventsCount = 0;
return this;
}
listeners = events[type];
if (typeof listeners === 'function') {
this.removeListener(type, listeners);
} else if (listeners) {
// LIFO order
do {
this.removeListener(type, listeners[listeners.length - 1]);
} while (listeners[0]);
}
return this;
}
listeners: function listeners(type) {
var evlistener;
var ret;
var events = this._events;
if (!events)
ret = [];
else {
evlistener = events[type];
if (!evlistener)
ret = [];
else if (typeof evlistener === ‘function’)
ret = [evlistener];
else
ret = arrayClone(evlistener, evlistener.length);
}
return ret;
}
listenerCount: function listenerCount(type) {
const events = this._events;
if (events) {
const evlistener = events[type];
if (typeof evlistener === 'function') {
return 1;
} else if (evlistener) {
return evlistener.length;
}
}
return 0;
}
eventNames: function eventNames() {
return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : [];
}
总结
通过上面的输出结果,顺便还可以看到注册的事件都是加到该实例上的,并且是键值对的形式