前言
Node.js也使用了很久了,但是原理却一直摸棱两可,最近读了《深入浅出Node.js》,了解到事件循环是整个的核心,因此,我开始了解其原理和events模块的部分实现。 基本的原理书里网上说得比我好太多了,我就不重复了。 了解了基本使用后,我尝试自己实现了一个。在实现中参考了很多别人写的以及评论区的改进说明,如果要自己实现我总结为以下几点:
属性:_events,_eventsCount
方法:on,off,once,emit,removeAllListeners_events
存放了所有的事件和事件的回调函数数组,_eventsCount
则是对所有的事件进行计数on
方法绑定事件,接受一个事件名type
和监听器listener
作为参数off
方法则是移除某个监听器,接受事件名type
和监听器listener
作为参数once
与on大同小异,但是once加入的监听器只执行一次。emit
触发事件,只要给定事件名type
就可以实现触发removeAllListeners
移除事件所有的监听器。
自定义实现代码
具体的代码如下所示,我为了同时巩固原来基础的语法没有使用ES6的语法,而是使用了原型的方法,可能写得也不咋滴,将就看看吧。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 function EventEmitter (options={} ){ this ._events ={}; this ._eventsCount =0 ; var _DEFAULT_MAX_LISTENERS=10 ; this ._maxListeners =options.maxListeners ?options.maxListeners :_DEFAULT_MAX_LISTENERS; } EventEmitter .prototype .on =function (type,listener ){ if (!this ._events ){ this ._events ={}; } if (this ._events [type]){ this ._events [type].push (listener); if (!this ._maxListeners !=0 && this ._events [type].length >this ._maxListeners ){ throw new RangeError ("监听器最大的数量是10个" ) } } else { this ._events [type]=[listener]; this ._eventsCount ++; } } EventEmitter .prototype .addListener =function (type,listener,options={once:false } ){ if (options.once ){ this .on (type,listener); } else { this .once (type,listener); } } EventEmitter .prototype .once =function (type,listener ){ var me=this ; function oneTime (...args ){ listener.call (me,...args); me.off (type,oneTime); } me.on (type,oneTime); } EventEmitter .prototype .removeListener =function (type,listener ){ if (this ._events [type]){ var index=this ._events [type].indexOf (listener); if (index>=0 ){ this ._events [type].splice (index,1 ); } } } EventEmitter .prototype .off =EventEmitter .prototype .removeListener ;EventEmitter .prototype .removeAllListeners =function (type ){ if (this ._events [type]){ this ._events [type]=[]; } } EventEmitter .prototype .emit =function (type,...args ){ if (this ._events [type]){ this ._events [type].forEach (fn => fn.call (this ,...args)) } } module .exports ={ EventEmitter }
就这样了,大家有什么问题欢迎评论区留言,以后抽空再写ES6语法的。
…… 2020-03-19补充ES6写法……
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 class EventEmitter { constructor ( ) { this ._events = Object .create ({}); } on (type, fn ) { if (!(typeof type == 'string' )) { throw new TypeError ('type must be string' ) } if (!(typeof fn === 'function' )) { throw new TypeError ('fn must be function!' ) } this ._events = this ._events || {}; let row = this ._events [type]; Array .isArray (row) ? '' : this ._events [type] = []; this ._events [type].push (fn); } off (type, fn ) { if (!(typeof type == 'string' )) { throw new TypeError ('type must be string' ) } if (!this ._events [type] || this ._events [type].length == 0 ) { return ; } if (!fn) { this ._events [type] = []; return } let fns = this ._events [type]; fns = fns.filter ((item ) => item !== fn); this ._events [type] = fns; } once (type, fn ) { if (!(typeof type == 'string' )) { throw new TypeError ('type must be string' ) } if (!(typeof fn === 'function' )) { throw new TypeError ('fn must be function!' ) } const context = this ; function oneFn (...args ) { fn.call (context, ...args); context.off (type, oneFn); } context.on (type, oneFn); } emit (type, ...args ) { if (!(typeof type == 'string' )) { throw new TypeError ('type must be string' ) } if (!this ._events [type] || this ._events [type].length == 0 ) { return ; } this ._events [type].forEach (fn => { fn.call (this , ...args); }); } }