本文共 4248 字,大约阅读时间需要 14 分钟。
node是单线程,基于事件驱动的,所以node中很多模块都是基于events去实现的,所以event模块在node中属于很重要的模块。
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());}复制代码
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;复制代码
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]; }}复制代码
EventEmitter.prototype.once = function(eventName,listener){ function once(){//once缓存listener,不然的话移除时找不到listener listener(); this.removeListener(eventName,once) } this.on(eventName,once)}复制代码
EventEmitter.prototype.emit = function(eventName,...args){ if(this._events[eventName]){ this._events.forEach(fn=>{//使用箭头函数,所以this指向外层的this即emit实例 fn.call(this,...args) }) }}复制代码
Events.prototype.removeListener = finction(eventName,listener){//需要从相应的事件队列中筛选排除传入的listener this._events[eventName].filter(fn=>{ return listener!==item &&item.g!===listener//第二个针对于用once绑定的事件回调 })}EventEmitter.prototype.once = function(eventName,listener){ function once(){//once缓存listener,不然的话移除时找不到listener listener(); this.removeListener(eventName,once) } once.g = listener;//用来缓存原来的listener,删除时用到 this.on(eventName,once)}复制代码
以上就是关于Events模块原理的介绍,如果有错误欢迎指正,本文参考: