当前位置: 首页 > 后端技术 > Node.js

【节点不完全参考西方】EventEmitter分析(事件发布-订阅模式)

时间:2023-04-03 20:34:00 Node.js

先从node异步编程方案说起:事件发布/订阅模式Promise/deferred模式流程控制库事件发布/订阅模式事件监听模式是异步编程中广泛使用的一种模式,它是回调函数的事件,并调用了发布/订阅模型。主要函数有onremoveonceemit,我们简单实现一个事件监听函数。我们先创建一个eventEmitter函数functionEventEmitter(){//使用Object.create(null)代替空对象{}//优点是没有杂质,不继承原型链//_events保存的信息observedqueuethis._events=Object.create(null);}因为listener过多占用大量内存,导致内存泄漏,所以数量一般不会超过10个,否则会有warning警告??接下来是一些默认的settings//默认最大绑定数EventEmitter.defaultMaxListeners=10;//同on方法EventEmitter.prototype.addListener=EventEmitter.prototype.on;//返回监听的事件名称EventEmitter.prototype.eventNames=function(){returnObject.keys(this._events);};//设置最大监听数EventEmitter.prototype.setMaxListeners=function(n){这。_count=n;};//返回监听器的数量EventEmitter.prototype.getMaxListeners=function(){returnthis._count?this._count:this.defaultMaxListeners;};接下来是on函数的实现EventEmitter.prototype.on=function(type,cb,flag){//如果不是newListener,newListener应该执行下面的if(type!=='newListener'){this._events['newListener']&&this._events['newListener'].forEach(listener=>{listener(type);});}if(this._events[type]){//根据传入的flag来决定是向前还是向后添加if(flag){this._events[type].unshift(cb);}else{this._events[type].push(cb);}}else{this._events[type]]=[cb];}//监听的事件不能超过设置的最大监听数}};分析:on函数是gang的初始函数。首先判断是不是第一次听。place,根据flag判断是在队尾还是队头添加回调函数。接下来是oncelisteningonce的实现方法//ListeningonceEventEmitter.prototype.once=function(type,cb,flag){//先绑定,再调用Deletefunctionwrap(){cb(...arguments);this.removeListener(类型,换行);}//自定义属性wrap.listen=cb;this.on(类型,换行,标志);};解析:实现是在回调上包裹一层remove操作,然后作为新的回调传入on函数。这样第一次执行回调的时候就会执行remove操作,执行一次就删除。操作之后是remove函数,它删除类型为EventEmitter.prototype.removeListener=function(type,cb){if(this._events[type]){this._events[type]=this._events[type]].filter(listener=>{returncb!==listener&&cb!==listener.listen;});}};分析:传入类型和要删除的回调,对类型标记的数组进行过滤操作,如果cbcb===listener则过滤掉并删除所有EventEmitter.prototype.removeAllListener=function(){this._events=Object.create(null);};接下来是发布函数emitEventEmitter.prototype.emit=function(type,...args){if(this._events[type]){this._events[type].forEach(listener=>{listener.call(this,...参数);});}};直观上,如果有events类型的监听队列,队列中的每个callback都会执行一次,使用call函数绑定this和arg完整代码//EventEmitter.jsfunctionEventEmitter(){//使用Object.create(null)insteadofanemptyobject{}//优点是没有杂质,不继承原型链。在方法EventEmitter.prototype.addListener上=EventEmitter.prototype.on;//返回监听的事件名EventEmitter.prototype.eventNames=function(){returnObject.keys(this._events);};//设置最大监听数EventEmitter.prototype.setMaxListeners=function(n){this._count=n;};//返回监听数EventEmitter.prototype.getMaxListeners=function(){returnthis._count?this._count:this.defaultMaxListeners;};//ListenEventEmitter.prototype.on=function(type,cb,flag){//默认值,如果没有_events,为其创建一个if(!this._events){this._events=Object.create(null);}//不是newListener应该让newListener执行以下操作;});}if(this._events[type]){//根据传入的flag决定是向前还是向后添加if(flag){this._events[type].unshift(cb);}else{this._events[type].push(cb);}}else{this._events[type]=[cb];}//监听的事件不能超过设置的最大监听数if(this._events[type].length===this.getMaxListeners()){console.warn('warning-warning-warning');}};//前置EventEmitter.prototype.prependListener=function(type,cb){this.on(type,cb,true);};EventEmitter.prototype.prependOnceListener=function(type,cb){this.once(type,cb,true);};//监听一次EventEmitter.prototype.once=function(type,cb,flag){//先绑定,调用functionwrap(){cb(...arguments)后删除this.removeListener(类型,换行);}//自定义属性wrap.listen=cb;this.on(type,wrap,flag);};//移除监听类型EventEmitter.prototype.removeListener=function(type,cb){if(this._events[type]){this._events[type]=this._events[type].filter(listener=>{returncb!==listener&&cb!==listener.listen;});}};EventEmitter.prototype.removeAllListener=function(){this._events=Object.create(null);};//返回所有监听类型EventEmitter.prototype.listeners=function(type){returnthis._events[type];};//发出EventEmitter.prototype.emit=function(type,...args){if(this._events[type]){this._events[type]].forEach(listener=>{listener.call(this,...args);});}};module.exports=EventEmitter;我的博客即将同步到腾讯云+社区,诚邀大家加入:https://cloud.tencent.com/dev...