Node.js EventEmitter

本文介绍了Node.js中事件驱动机制的基础知识,展示了如何使用EventEmitter类实现事件监听和触发的功能。通过具体示例代码,解释了事件绑定、监听、移除等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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) : [];
}


总结

通过上面的输出结果,顺便还可以看到注册的事件都是加到该实例上的,并且是键值对的形式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值