简单的写一个发布订阅器
發(fā)布-訂閱模式在開發(fā)中的應(yīng)用其實(shí)是很廣泛的,比如大家都知道的 Vue,使用數(shù)據(jù)驅(qū)動(dòng)模板的改變,將我們的雙手從繁瑣的 dom 操作中解放出來,稍微懂一些原理的同學(xué)們都知道,其雙向數(shù)據(jù)綁定就是通過數(shù)據(jù)劫持、發(fā)布-訂閱和 dom 模板編譯實(shí)現(xiàn)的,就算不了解這個(gè)的同學(xué),js 中的事件監(jiān)聽相信做前端開發(fā)的同學(xué)都寫過;
其實(shí)事件監(jiān)聽就是一個(gè)訂閱的操作,當(dāng)某個(gè)事件觸發(fā)的時(shí)候,對(duì)該事件監(jiān)聽時(shí)傳入的 callback 就會(huì)被執(zhí)行,這就是一個(gè)完整的發(fā)布的-訂閱流程;接下來我們就來簡(jiǎn)單的寫一下一個(gè)發(fā)布訂閱器:
思路:
俗話說:磨刀不誤砍柴工,在動(dòng)手之前,縷清一下思路是有必要的,首先我們要明確這個(gè)發(fā)布訂閱器的功能,其中包括
基本功能:
- 可添加訂閱者
- 可觸發(fā)消息通知某個(gè)訂閱器執(zhí)行其中的所有訂閱者
- 可刪除指定訂閱者
升級(jí)功能:
- 可同時(shí)給多個(gè)訂閱器添加訂閱者
- 可刪除指定訂閱器中的所有訂閱者
- 可指定同時(shí)刪除多個(gè)訂閱器或者直接清空所有訂閱器
- 可添加一次性訂閱(該訂閱者一旦被執(zhí)行,就會(huì)在訂閱器中移除)
- 處理好 this 指向和實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用
- 添加錯(cuò)誤判斷和提醒機(jī)制
接下來我們就分兩版上代碼:
基礎(chǔ)版
/*** 發(fā)布訂閱器構(gòu)造函數(shù)*/ var Publisher = (function() {function Publisher() {this._subs = {}; // 維護(hù)一個(gè)訂閱器列表}/*** 添加訂閱者* 若訂閱者需要插入的訂閱器不存在,則新創(chuàng)建一個(gè)* @param { string } type - 需要添加訂閱者的訂閱器名* @param { function } func - 訂閱者*/Publisher.prototype.addSub = function(type, func) {if(!this._subs[type]) this._subs[type] = [];this._subs[type].push(func);};/*** 發(fā)布通知* 通知指定訂閱器執(zhí)行其中的每個(gè)訂閱者* @param { string } type - 需要通知其發(fā)布消息的訂閱器名*/Publisher.prototype.notify = function(type) {if(!this._subs[type]) return;var args = Array.prototype.slice.call(arguments, 1);this._subs[type].forEach(function(item) {item.apply(this, args);}, this);};/*** 刪除訂閱者* @param { string } type - 指定操作的訂閱器名* @param { function } func - 指定需要?jiǎng)h除的訂閱者*/Publisher.prototype.destory = function(type, func) {this._subs[type].forEach(function(item, index, array) {(item === func) && array.splice(index, 1);}, this);};return Publisher; }()); 復(fù)制代碼基礎(chǔ)版就如上面的代碼,以最簡(jiǎn)單的方式實(shí)現(xiàn)一個(gè)發(fā)布訂閱器的基本功能(能訂閱,并能接收消息,還能指定刪除)
升級(jí)版:
/*** 發(fā)布訂閱器構(gòu)造函數(shù)*/ var Publisher = (function() {function Publisher() {this._subs = {};}/*** 添加訂閱者* 若訂閱者需要插入的訂閱器不存在,則新創(chuàng)建一個(gè)* 若傳入的訂閱器名為一個(gè)數(shù)組,則遍歷數(shù)組內(nèi)的每個(gè)訂閱器添加訂閱者* @param { string|Array<string> } type - 需要添加訂閱者的訂閱器名* @param { function } func - 訂閱者* @returns { object } - 發(fā)布器實(shí)例,可實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用*/Publisher.prototype.addSub = function(type, func) {if(Array.isArray(type)) {type.forEach(function(item) {this.addSub(item, func);}, this);} else {(this._subs[type] || (this._subs[type] = [])).push(func);}return this;};/*** 添加單次訂閱* 當(dāng)該訂閱者在被通知執(zhí)行一次之后會(huì)從訂閱器中移除* @param { string|Array<string> } type - 需要添加訂閱者的訂閱器名* @param { function } func - 訂閱者* @returns { object } - 發(fā)布器實(shí)例,可實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用*/Publisher.prototype.once = function(type, func) {function onceAdd() {var args = Array.prototype.slice(arguments);this.destory(type, onceAdd);func.apply(this, args);}this.addSub(type, onceAdd);return this;};/*** 發(fā)布通知* 通知指定訂閱器執(zhí)行其中的每個(gè)訂閱者* @param { string } type - 需要通知其發(fā)布消息的訂閱器名* @returns { object } - 發(fā)布器實(shí)例,可實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用*/Publisher.prototype.notify = function(type) {if(this._subs[type] === void 0) throw TypeError("Can't find the " + type + " event in the Publisher");var args = Array.prototype.slice.call(arguments, 1);this._subs[type].forEach(function(item) {item.apply(this, args);}, this);return this;};/*** 刪除訂閱器/訂閱者* 若沒有傳入?yún)?shù)直接調(diào)用方法,將清空整個(gè)訂閱器列表* 若只傳入了訂閱器類型參數(shù),沒有指定刪除的訂閱者,則刪除該訂閱器* @param { string|Array<string> } type - 指定操作的訂閱器名,可用數(shù)組傳入多個(gè)需要操作的訂閱器名* @param { function } func - 指定需要?jiǎng)h除的訂閱者* @return { object } - 發(fā)布器實(shí)例,可實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用*/Publisher.prototype.destory = function(type, func) {if(func && typeof func !== 'function') throw TypeError('The param "func" should be a function!');if(!arguments.length) {this._subs = {};return this;}if(Array.isArray(type)) {type.forEach(function(item) {this.destory(item, func);}, this);}if(!func) {delete this._subs[type];} else {this._subs[type].forEach(function(item, index, array) {(item === func) && array.splice(index, 1);}, this);}return this;};return Publisher; }()); 復(fù)制代碼以上就是一個(gè)簡(jiǎn)單的發(fā)布訂閱器了,若有什么不足的地方,還望各位同學(xué)指正!
轉(zhuǎn)載于:https://juejin.im/post/5b2602edf265da59aa2d879f
總結(jié)
以上是生活随笔為你收集整理的简单的写一个发布订阅器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中南大学夏令营集训营
- 下一篇: 卷积(转自wiki百科)