publish/subscribe(發布/訂閱)模式
阿新 • • 發佈:2019-05-09
事件 互調 有意思 this 標識符 ken con strong scrip 這幾天看《JavaScript設計模式》看的雲裏霧裏的,設計模式看似是具體的東西,卻又抓不住。在想發布/訂閱模式的形態時,開啟新思路,有所收獲。
化繁為簡分析,倒推分析; 化簡為繁,是實際項目。
實際場景
有一個函數,所傳參數不同執行結果不同;
另一個函數,所傳參數不同執行結果不同... 有很多參數
正常情況我們會把代碼羅列下來,就像積木一樣, 這樣看起來整個代碼比較雜亂,如果函數之間相互調用會更亂,也不易於維護。
有問題就要解決,聰明的前輩們根據現象,思考出從各個維度對代碼進行優化,總結出使用頻率高的方式方法,也就是設計模式。
設計模式其實是一種形式。
基於上述問題解決方法
倒推的方式,先實現後調用
模塊功能
定義一個存放函數的對象topics
把實現不同功能的函數存放到定義的對象裏,動態添加對象屬性,對象每個屬性是存放對應功能函數和其編號
*topics= {
"topic1":[{token:0, fn}],
"topic2":[{token:1, fn1}],
"topic3":[{token:2, fn2}],
"topic3":[{token:3, fn2}]
}
定義一個全局對象,把處理上述添加對應的執行函數,以及根據參數執行功能函數掛載到這個對象上。
// 定義一個全局對象,掛載處理函數事件
let pubsub = {};
// 定義一個立即執行的匿名函數,生成獨立的作用域, es6中可以使用{}形成獨立的作用域,但是不能傳參
(function (q) {
let topicObj = {},
subUid = -1;
// 訂閱方法,也是添加函數的方法
// topic是作為動態的屬性名, fn是對應的執行函數
q.subscribe = (topic, fn) =>{
// 判斷topicObj對象中是否有對應的topic屬性,如果沒有則設置為數組
if(!topicObj[topic]){
topicObj[topic] = []
}
// 下標計算,是屬性值,所以要轉化為字符串
let token = (++subUid).toString()
// 添加到數組中
topicObj[topic].push({
token:token,
fn:fn
})
//console.log( topicObj )
//return唯一的標識符token,用於刪除指定的項
return token;
}
// 發布方法,也是執行函數
q.publish = (topic, args)=> {
if(!topicObj[topic])return;
// 獲取指定topic屬性項,並獲取長度
let subscribes = topicObj[topic],
len = subscribes.length;
//console.log(--len);
// 遍歷並執行
while (len--){
// 回調函數有2個參數,一個表示屬於對像的屬性,另一個則是變量,在定義函數的時候要註意
subscribes[len].fn(topic, args);
}
return this;
}
// 刪除訂閱者,即對象中指定的屬性,也就是對應動態添加的函數
q.delScribe = (token)=>{
for(let key in topicObj){
topicObj[key].forEach((item, i)=>{
if(item.token===token){
topicObj[key].splice(i,1)
}
})
}
console.log( topicObj )
return this;
}
})(pubsub);
//console.log(pubsub);
//測試
let msg = (data)=>{
// 這裏還可以執行其它相關的函數
console.log(‘data---‘,data);
}
pubsub.subscribe(‘test‘, msg);
pubsub.publish(‘test‘, ‘這是數據‘);
//pubsub.delScribe(‘0‘);
~~~~匿名函數的使用,也是很有意思的
《JavaScript設計模式》之 publish/subscribe(發布/訂閱)模式
publish/subscribe(發布/訂閱)模式