前言
一個(gè)多月前,面試時(shí)被問到發(fā)布-訂閱模式,面試完就查閱資料學(xué)習(xí)了下踩验。這篇文章我將記錄我對(duì)此的理解并用Javascript代碼實(shí)現(xiàn)發(fā)布-訂閱模式。
介紹
用一個(gè)全局對(duì)象商玫,負(fù)責(zé)模塊間的通信箕憾,具體落實(shí)發(fā)布和訂閱兩種功能。發(fā)布者不需要知道訂閱者决帖,訂閱者不需要知道發(fā)布者厕九,發(fā)布者能啟動(dòng)功能器使訂閱者收到消息,這就足夠了
優(yōu)勢(shì)
1地回、統(tǒng)一管理
訂閱模式中扁远,可以抽離出調(diào)度中心單獨(dú)成一個(gè)文件,可以對(duì)一系列的訂閱事件進(jìn)行統(tǒng)一管理刻像。
2畅买、松耦合
發(fā)布者不需要知道訂閱者的數(shù)量,訂閱者聽得話題或者訂閱者是通過什么方式運(yùn)行的细睡。他們能夠相互獨(dú)立地運(yùn)行谷羞,這樣就可以讓你分開開發(fā)這兩部分而不需要擔(dān)心對(duì)狀態(tài)或?qū)崿F(xiàn)的任何細(xì)微的影響。
缺點(diǎn)
1溜徙、狀態(tài)未知
發(fā)布者不知道訂閱者的狀態(tài)湃缎,反之亦然,這樣的話蠢壹,你根本不知道在另一端是否會(huì)沒有問題嗓违?
2、不能識(shí)別惡意消息
攻擊者(惡意的發(fā)布者)能夠入侵系統(tǒng)并且撕開它图贸。這會(huì)導(dǎo)致惡意的消息被發(fā)布蹂季,訂閱者能夠獲得他們以前并不能獲得的消息冕广。
3、關(guān)系更新難
更新發(fā)布者和訂閱者的關(guān)系會(huì)是一個(gè)很難的問題偿洁,因?yàn)楫吘顾麄兏静徽J(rèn)識(shí)對(duì)方撒汉。
代碼實(shí)現(xiàn)
1、發(fā)布-訂閱模塊實(shí)現(xiàn)
//publish-subscribe.js
var publishEvents = (function () {
var listen,log,obj, one, remove, trigger, __this;
obj = {};
__this = this;
listen = function( key, eventfn ) { // 訂閱
var stack, _ref;
stack = ( _ref = obj[key] ) != null ? _ref : obj[ key ] = [];
return stack.push( eventfn );
};
one = function( key, eventfn ) { //只能被一個(gè)訂閱者訂閱
remove( key );
return listen( key, eventfn );
};
remove = function( key ) { // 解除
var _ref;
return ( _ref = obj[key] ) != null ? _ref.length = 0 : void 0;
};
trigger = function() { // 發(fā)布
var fn, stack, _i, _len, _ref, key;
key = Array.prototype.shift.call( arguments );
stack = ( _ref = obj[ key ] ) != null ? _ref : obj[ key ] = [];
for ( _i = 0, _len = stack.length; _i < _len; _i++ ) {
fn = stack[ _i ];
if( fn == undefined ) return false;
if ( fn.apply( __this, arguments ) === false) {
return false;
}
}
}
return {
listen: listen,
one: one,
remove: remove,
trigger: trigger
}
})();
module.exports = publishEvents;
2涕滋、模塊使用
//test-publish-subscribe.js
var pubSub = require('./publish-subscribe');
var testStr = 'testStr';
pubSub.listen(testStr, function() {
console.log('pubSub.listen');
});
setTimeout(function() {
console.log('1秒后的 pubSub.trigger')
pubSub.trigger(testStr);
pubSub.remove(testStr);
}, 1000);
setTimeout(function() {
console.log('2秒后的 pubSub.trigger');
pubSub.trigger(testStr);
}, 2000);
3睬辐、結(jié)果
最后
如果有疑問,請(qǐng)下載示例代碼何吝,也可以歡迎私信或者留言給我溉委。
如果覺得對(duì)你有幫助,請(qǐng)點(diǎn)個(gè)??爱榕,謝謝