nodeJS之eventproxy源码解读

1.源码缩影

    !(function (name, definition) { var hasDefine = typeof define === 'function', //检查上下文环境是否为AMD或CMD hasExports = typeof module !== 'undefined' && module.exports; //检查上下文环境是否为Node if (hasDefine) { define(definition); //AMD环境或CMD环境 } else if (hasExports) { module.exports = definition(require('debug')('eventproxy')); //构建为普通Node模块 } else { this[name] = definition(); //构建在window.name中 } })('EventProxy', function (debug) { debug = debug || function () {}; //为debug设置默认值 var EventProxy = function () { //EventProxy构造函数 if (!(this instanceof EventProxy)) { //防止构造函数以call或apply方式被其它对象调用,只能new return new EventProxy(); } this._callbacks = {}; //new之后对象属性_callbacks,保存要处理的回调函数 this._fired = {}; //new之后对象属性_fired,保存回调之后的结果 }; EventProxy.prototype... //EventProxy的诸原型函数,所谓原型函数,就是这些函数为new之后对象多共享 EventProxy.create = function () {...}; //EventProxy的属性create,指向普通函数 EventProxy.EventProxy = EventProxy; //EventProxy的属性EventProxy指向自身 return EventProxy; //返回EventProxy构造函数 });

源码解读: 上面大致展示了eventproxy的结构,首先它使用闭包的形式保证了代码的整洁;其次为了适应不同的使用场合,代码中都做了必要的处理,而我们使用最多的无疑是作为nodejs的模块:检查exports,如果存在,则构建为nodejs模块:module.exports = definition(require(‘debug’)(‘eventproxy’));而definition则是function(debug)开始一直到文件结构的函数,其中debug作为调试,暂且不管,剩下的就是EventProxy函构造函数,EventProxy原型函数,EventProxy.create一般函数,最后返回EventProxy函构造函数.于是构建的结果相当于module.exports = EventProxy;所以在其它模块中的require(“eventproxy”)指向的就是EventProxy构造函数.

2.原型函数addListener,别名bind,on,subscribe

    EventProxy.prototype.addListener = function (ev, callback) { debug('Add listener for %s', ev); this._callbacks[ev] = this._callbacks[ev] || []; this._callbacks[ev].push(callback); return this; };

源码解读: 该方法接收两个参数:事件名称和回调函数,首先在_callbacks对象上面开辟事件的数组,之后把回调函数放进该数组中.

3.原型函数headbind

    EventProxy.prototype.headbind = function (ev, callback) { debug('Add listener for %s', ev); this._callbacks[ev] = this._callbacks[ev] || []; this._callbacks[ev].unshift(callback); return this; };

源码解读: 该方法与addListene方法相同,只不过是把回调函数放在了数组的第一个

4.原型函数removeListener,别名unbind

    EventProxy.prototype.removeListener = function (eventName, callback) { var calls = this._callbacks; if (!eventName) { debug('Remove all listeners'); this._callbacks = {}; } else { if (!callback) { debug('Remove all listeners of %s', eventName); calls[eventName] = []; } else { var list = calls[eventName]; if (list) { var l = list.length; for (var i = 0; i < l; i++) { if (callback === list[i]) { debug('Remove a listener of %s', eventName); list[i] = null; } } } } } return this; };

源码解读: 该方法是为移除特定的回调函数:(1)两个参数都不存在,移除所有回调函数(2)eventName存在,callback不存在,移除eventName上的所有函数(3)eventName存在,callback存在,移除eventName上的callback函数.

5.原型函数removeAllListeners

    EventProxy.prototype.removeAllListeners = function (event) { return this.unbind(event); };

源码解读: 该方法是为移除event上所有的函数.

6.原型函数bindForAll

    EventProxy.prototype.bindForAll = function (callback) { this.bind(ALL_EVENT, callback); };

源码解读: 该方法是为绑定全局回调函数 all为callback

7.原型函数unbindForAll

    EventProxy.prototype.unbindForAll = function (callback) { this.unbind(ALL_EVENT, callback); };

源码解读: 该方法是为移除全局回调函数all的callback函数

8.原型函数trigger,别名emit,fire

    EventProxy.prototype.trigger = function (eventName, data) { var list, ev, callback, args, i, l; var both = 2; var calls = this._callbacks; debug('Emit event %s with data %j', eventName, data); while (both--) { //执行两次,第一次执行eventName的回调函数,第二次执行全局__all__的回调函数 ev = both ? eventName : ALL_EVENT; list = calls[ev]; //回调函数列表 if (list) { for (i = 0, l = list.length; i < l; i++) { if (!(callback = list[i])) { //如果回调函数不存在,移除 list.splice(i, 1); i--; l--; } else { args = both ? SLICE.call(arguments, 1) : arguments; callback.apply(this, args); //非全局回调函数,值传入data,全局传入全部参数 } } } } return this; };

源码解读: 该方法是为eventName事件触发函数,或对eventName事件注值函数:(1)事件触发会做两件事情,一是触发该事件的函数数组,把data出入一一执行,二是执行全局回调函数数组,把事件名称和data传进去,它内部会判断是否所有要处理的事件都已处理完毕,处理完毕就执行后面真正的全局回调,如果没有完成则会退出全局回调函数.

9.原型函数once

    EventProxy.prototype.once = function (ev, callback) { var self = this; var wrapper = function () { callback.apply(self, arguments); //回调wrapper时回调源回调函数,再解绑 self.unbind(ev, wrapper); }; this.bind(ev, wrapper); //绑定的是wrapper,会回调wrapper return this; };

源码解读: 该方法是为一次性绑定函数,即回调之后会移除,是最常用的绑定函数,它绑定的不是原有回调函数,而是进行了包装,因为在包装内部要做解绑处理;虽然进行了包装,但是回调的时候传入的参数还是在内部传入远回调函数执行,只是多了一步解绑.

10.临时变量later

    var later = typeof process !== 'undefined' && process.nextTick || function (fn) { setTimeout(fn, 0); };

源码解读: 存在process.nextTick,later就等于process.nextTick,没有就用setTimeout.

11.原型函数emitLater

    EventProxy.prototype.emitLater = function () { var self = this; var args = arguments; later(function () { self.trigger.apply(self, args); }); };

源码解读: 迟缓触发,参数应为eventName,data.

12.原型函数immediate,别名asap

    EventProxy.prototype.immediate = function (ev, callback, data) { this.bind(ev, callback); this.trigger(ev, data); return this; };

源码解读: 即时的,绑定事件回调函数,触发

13.临时变量_assign

    var _assign = function (eventname1, eventname2, cb, once) { var proxy = this; var argsLength = arguments.length; //参数个数 var times = 0; //已触发注值个数 var flag = {}; //已触发注值标志 // Check the arguments length. if (argsLength < 3) { //参数小于3,返回 return this; } var events = SLICE.call(arguments, 0, -2); //取得传入的event数组 var callback = arguments[argsLength - 2]; //取得回调函数 var isOnce = arguments[argsLength - 1]; //取得是否一次调用标志 // Check the callback type. if (typeof callback !== "function") { //没有回调函数,返回 return this; } debug('Assign listener for events %j, once is %s', events, !!isOnce); var bind = function (key) { //为处理回调函数 var method = isOnce ? "once" : "bind"; //根据标志取得调用绑到的方法 proxy[method](key, function (data) { //绑定事件和回调函数,回调函数为内建,回调的时候会传入data参数 proxy._fired[key] = proxy._fired[key] || {}; //初始化结果保存位置 proxy._fired[key].data = data; //把数据注入_fired中 if (!flag[key]) { //没有回调过,标志置为true,事件回调个数+1 flag[key

转载于:https://www.cnblogs.com/zhishaofei/p/4319351.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值