node不懂Events模块没法玩了

Events的重要性:

node是单线程,基于事件驱动的,所以node中很多模块都是基于events去实现的,所以event模块在node中属于很重要的模块。

Events常用的API:

  1. emitter.on(eventName, listener)和emitter.addListener(eventName, listener)用来添加订阅事件
  2. emitter.once(eventName, listener)用来添加只执行一次的事件
  3. emitter.prependListener(eventName, listener)用来在事件队列前面添加事件
  4. emitter.emit(eventName[, ...args])用来触发事件队列执行
  5. emitter.removeListener(eventName, listener)用来移除某个事件队列
  6. EventEmitter.defaultMaxListeners 默认事件队列的长度
  7. emitter.setMaxListeners 设置最大队列的长度
  8. emitter.prototype.getMaxListeners 获取最大队列的长度

Event的核心原理:

events模块是基于发布订阅模式来实现的,其核心的逻辑可以用下面的代码表示:

function Event(){this.events=[];
}
//添加订阅者
Events.prototype.on = function(listener){if(typeof listener === 'function'){this.events.push(listener)}
}
//执行订阅回调
Events.prototype.emit = function(){this.events.forEach(event=>evetn());
}
复制代码

Events.prototype.on 实现

function EventEmitter(){this._events={};//用来存储各种不同类型的事件队列this._maxListeners = undefined; // 默认实例上没有最大监听数
}EventEmitter.defaultMaxListeners//默认事件队列的长度为10EventEmitter.prototype.setMaxListeners = function(count){this._maxListeners = count;
}EventEmitter.prototype.getMaxListeners = function(){if(!this._maxListeners){ // 如果没设置过那就是10个return EventEmitter.defaultMaxListeners;}return this._maxListeners
}
EventEmitter.prototype.on = EventEmitter.prototype.addListener=function(eventName,listener){if(!this._events){this._events = Object.create(null);}//防止缓存不存在,创建一个没有原型的干净缓存if(eventName!=='newListener'){//newListener每次绑定事件都会调用这个里面的回调并且传入当前事件名if(this._events['newListener']){this._events['newListener'].forEach(fn=>fn(eventsName))}}if(this.events[eventName]){//已存在队列就直接将回调放入if(this._events[eventName].length === this.getMaxListeners()){console.warn(`Possible EventEmitter memory leak detected.${this._events[eventName].length}${String(eventName)}listeners added. Use emitter.setMaxListeners() toincrease limit'`)}this._events[eventName].push(callback);}else{//不存在就创建一个队列再放入if(this._events[eventName].length === this.getMaxListeners()){console.warn(`Possible EventEmitter memory leak detected.${this._events[eventName].length}${String(eventName)}listeners added. Use emitter.setMaxListeners() toincrease limit'`)}this._events[eventsName]=[listener];}
}
module.exports = EventEmitter;
复制代码

Events.prototype.prependListener 实现

EventEmitter.prototype.prependListener = function (eventName,listener) {this.on(eventName,listener, true);
}
//修改EventEmitter.prototype.on让其可以选择添加事件的位置
EventEmitter.prototype.on = EventEmitter.prototype.addListener=function(eventName,listener,flag){if(!this._events){this._events = Object.create(null);}if(eventName!=='newListener'){if(this._events['newListener']){this._events['newListener'].forEach(fn=>fn(eventsName))}}if(this.events[eventName]){if(!flag){//根据flag来判断添加的位置this._events[eventName].push(callback);}else{this._events[eventName].unshift(callback);   }}else{this._events[eventsName]=[listener];}
}
复制代码

Events.prototype.once 实现

EventEmitter.prototype.once = function(eventName,listener){function once(){//once缓存listener,不然的话移除时找不到listenerlistener();this.removeListener(eventName,once)}this.on(eventName,once)
}
复制代码

Events.prototype.emit 实现

EventEmitter.prototype.emit = function(eventName,...args){if(this._events[eventName]){this._events.forEach(fn=>{//使用箭头函数,所以this指向外层的this即emit实例fn.call(this,...args)})}
}
复制代码

Events.prototype.removeListener 实现

Events.prototype.removeListener = finction(eventName,listener){//需要从相应的事件队列中筛选排除传入的listenerthis._events[eventName].filter(fn=>{return listener!==item &&item.g!===listener//第二个针对于用once绑定的事件回调})
}
EventEmitter.prototype.once = function(eventName,listener){function once(){//once缓存listener,不然的话移除时找不到listenerlistener();this.removeListener(eventName,once)}once.g = listener;//用来缓存原来的listener,删除时用到this.on(eventName,once)
}
复制代码

结语:

以上就是关于Events模块原理的介绍,如果有错误欢迎指正,本文参考:

  1. Node API
  2. javascript设计模式


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部