nodeJS之eventproxy源码解读
1.源碼縮影
!(function (name, definition) { var hasDefine = typeof define === 'function', //檢查上下文環(huán)境是否為AMD或CMD hasExports = typeof module !== 'undefined' && module.exports; //檢查上下文環(huán)境是否為Node if (hasDefine) { define(definition); //AMD環(huán)境或CMD環(huán)境 } else if (hasExports) { module.exports = definition(require('debug')('eventproxy')); //構(gòu)建為普通Node模塊 } else { this[name] = definition(); //構(gòu)建在window.name中 } })('EventProxy', function (debug) { debug = debug || function () {}; //為debug設(shè)置默認(rèn)值 var EventProxy = function () { //EventProxy構(gòu)造函數(shù) if (!(this instanceof EventProxy)) { //防止構(gòu)造函數(shù)以call或apply方式被其它對象調(diào)用,只能new return new EventProxy(); } this._callbacks = {}; //new之后對象屬性_callbacks,保存要處理的回調(diào)函數(shù) this._fired = {}; //new之后對象屬性_fired,保存回調(diào)之后的結(jié)果 }; EventProxy.prototype... //EventProxy的諸原型函數(shù),所謂原型函數(shù),就是這些函數(shù)為new之后對象多共享 EventProxy.create = function () {...}; //EventProxy的屬性create,指向普通函數(shù) EventProxy.EventProxy = EventProxy; //EventProxy的屬性EventProxy指向自身 return EventProxy; //返回EventProxy構(gòu)造函數(shù) }); 源碼解讀: 上面大致展示了eventproxy的結(jié)構(gòu),首先它使用閉包的形式保證了代碼的整潔;其次為了適應(yīng)不同的使用場合,代碼中都做了必要的處理,而我們使用最多的無疑是作為nodejs的模塊:檢查exports,如果存在,則構(gòu)建為nodejs模塊:module.exports = definition(require(‘debug’)(‘eventproxy’));而definition則是function(debug)開始一直到文件結(jié)構(gòu)的函數(shù),其中debug作為調(diào)試,暫且不管,剩下的就是EventProxy函構(gòu)造函數(shù),EventProxy原型函數(shù),EventProxy.create一般函數(shù),最后返回EventProxy函構(gòu)造函數(shù).于是構(gòu)建的結(jié)果相當(dāng)于module.exports = EventProxy;所以在其它模塊中的require(“eventproxy”)指向的就是EventProxy構(gòu)造函數(shù).
2.原型函數(shù)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; }; 源碼解讀: 該方法接收兩個參數(shù):事件名稱和回調(diào)函數(shù),首先在_callbacks對象上面開辟事件的數(shù)組,之后把回調(diào)函數(shù)放進(jìn)該數(shù)組中.
3.原型函數(shù)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方法相同,只不過是把回調(diào)函數(shù)放在了數(shù)組的第一個
4.原型函數(shù)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; }; 源碼解讀: 該方法是為移除特定的回調(diào)函數(shù):(1)兩個參數(shù)都不存在,移除所有回調(diào)函數(shù)(2)eventName存在,callback不存在,移除eventName上的所有函數(shù)(3)eventName存在,callback存在,移除eventName上的callback函數(shù).
5.原型函數(shù)removeAllListeners
EventProxy.prototype.removeAllListeners = function (event) { return this.unbind(event); }; 源碼解讀: 該方法是為移除event上所有的函數(shù).
6.原型函數(shù)bindForAll
EventProxy.prototype.bindForAll = function (callback) { this.bind(ALL_EVENT, callback); }; 源碼解讀: 該方法是為綁定全局回調(diào)函數(shù) all為callback
7.原型函數(shù)unbindForAll
EventProxy.prototype.unbindForAll = function (callback) { this.unbind(ALL_EVENT, callback); }; 源碼解讀: 該方法是為移除全局回調(diào)函數(shù)all的callback函數(shù)
8.原型函數(shù)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--) { //執(zhí)行兩次,第一次執(zhí)行eventName的回調(diào)函數(shù),第二次執(zhí)行全局__all__的回調(diào)函數(shù) ev = both ? eventName : ALL_EVENT; list = calls[ev]; //回調(diào)函數(shù)列表 if (list) { for (i = 0, l = list.length; i < l; i++) { if (!(callback = list[i])) { //如果回調(diào)函數(shù)不存在,移除 list.splice(i, 1); i--; l--; } else { args = both ? SLICE.call(arguments, 1) : arguments; callback.apply(this, args); //非全局回調(diào)函數(shù),值傳入data,全局傳入全部參數(shù) } } } } return this; }; 源碼解讀: 該方法是為eventName事件觸發(fā)函數(shù),或?qū)ventName事件注值函數(shù):(1)事件觸發(fā)會做兩件事情,一是觸發(fā)該事件的函數(shù)數(shù)組,把data出入一一執(zhí)行,二是執(zhí)行全局回調(diào)函數(shù)數(shù)組,把事件名稱和data傳進(jìn)去,它內(nèi)部會判斷是否所有要處理的事件都已處理完畢,處理完畢就執(zhí)行后面真正的全局回調(diào),如果沒有完成則會退出全局回調(diào)函數(shù).
9.原型函數(shù)once
EventProxy.prototype.once = function (ev, callback) { var self = this; var wrapper = function () { callback.apply(self, arguments); //回調(diào)wrapper時回調(diào)源回調(diào)函數(shù),再解綁 self.unbind(ev, wrapper); }; this.bind(ev, wrapper); //綁定的是wrapper,會回調(diào)wrapper return this; }; 源碼解讀: 該方法是為一次性綁定函數(shù),即回調(diào)之后會移除,是最常用的綁定函數(shù),它綁定的不是原有回調(diào)函數(shù),而是進(jìn)行了包裝,因?yàn)樵诎b內(nèi)部要做解綁處理;雖然進(jìn)行了包裝,但是回調(diào)的時候傳入的參數(shù)還是在內(nèi)部傳入遠(yuǎn)回調(diào)函數(shù)執(zhí)行,只是多了一步解綁.
10.臨時變量later
var later = typeof process !== 'undefined' && process.nextTick || function (fn) { setTimeout(fn, 0); }; 源碼解讀: 存在process.nextTick,later就等于process.nextTick,沒有就用setTimeout.
11.原型函數(shù)emitLater
EventProxy.prototype.emitLater = function () { var self = this; var args = arguments; later(function () { self.trigger.apply(self, args); }); }; 源碼解讀: 遲緩觸發(fā),參數(shù)應(yīng)為eventName,data.
12.原型函數(shù)immediate,別名asap
EventProxy.prototype.immediate = function (ev, callback, data) { this.bind(ev, callback); this.trigger(ev, data); return this; }; 源碼解讀: 即時的,綁定事件回調(diào)函數(shù),觸發(fā)
13.臨時變量_assign
var _assign = function (eventname1, eventname2, cb, once) { var proxy = this; var argsLength = arguments.length; //參數(shù)個數(shù) var times = 0; //已觸發(fā)注值個數(shù) var flag = {}; //已觸發(fā)注值標(biāo)志 // Check the arguments length. if (argsLength < 3) { //參數(shù)小于3,返回 return this; } var events = SLICE.call(arguments, 0, -2); //取得傳入的event數(shù)組 var callback = arguments[argsLength - 2]; //取得回調(diào)函數(shù) var isOnce = arguments[argsLength - 1]; //取得是否一次調(diào)用標(biāo)志 // Check the callback type. if (typeof callback !== "function") { //沒有回調(diào)函數(shù),返回 return this; } debug('Assign listener for events %j, once is %s', events, !!isOnce); var bind = function (key) { //為處理回調(diào)函數(shù) var method = isOnce ? "once" : "bind"; //根據(jù)標(biāo)志取得調(diào)用綁到的方法 proxy[method](key, function (data) { //綁定事件和回調(diào)函數(shù),回調(diào)函數(shù)為內(nèi)建,回調(diào)的時候會傳入data參數(shù) proxy._fired[key] = proxy._fired[key] || {}; //初始化結(jié)果保存位置 proxy._fired[key].data = data; //把數(shù)據(jù)注入_fired中 if (!flag[key]) { //沒有回調(diào)過,標(biāo)志置為true,事件回調(diào)個數(shù)+1 flag[key
轉(zhuǎn)載于:https://www.cnblogs.com/zhishaofei/p/4319351.html
總結(jié)
以上是生活随笔為你收集整理的nodeJS之eventproxy源码解读的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 起个网名微信的女生
- 下一篇: 关于chrome等浏览器不支持showM