node不懂Events模块没法玩了
Events的重要性:
node是单线程,基于事件驱动的,所以node中很多模块都是基于events去实现的,所以event模块在node中属于很重要的模块。
Events常用的API:
- emitter.on(eventName, listener)和emitter.addListener(eventName, listener)用来添加订阅事件
- emitter.once(eventName, listener)用来添加只执行一次的事件
- emitter.prependListener(eventName, listener)用来在事件队列前面添加事件
- emitter.emit(eventName[, ...args])用来触发事件队列执行
- emitter.removeListener(eventName, listener)用来移除某个事件队列
- EventEmitter.defaultMaxListeners 默认事件队列的长度
- emitter.setMaxListeners 设置最大队列的长度
- 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模块原理的介绍,如果有错误欢迎指正,本文参考:
- Node API
- javascript设计模式
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
