前端異步解決方案-2(發佈/訂閱模式);

什麼是發佈訂閱模式

什麼是發佈訂閱模式我這裏很少就很少闡述了,給你們提供幾個我以爲講的比較好的博文,請各位自行閱讀
發佈-訂閱模式解釋 這一篇文章應該是一個java coder寫的,可是設計模式這種東西並不分語言,各位能夠借鑑一下
Javascript中理解發布--訂閱模式這一篇是咱們前端人寫的,可是比較長,你們有耐心能夠看看html

發佈中心實現

我對發佈中心的實現,能夠不看(看了可以更好的理解發布訂閱模式)前端

//實現發佈中心
/*
* log=[{
*   index: Number,                日誌編號(自增)
*   type: String,                 日誌類型('subscribe','unsubscribe','publish')
*   eventName: String,            事件名
*   time: new Date(),             時間
*   fun:Function                 訂閱/取訂的方法(只有日誌類型爲'subscribe'或'unsubscribe'的纔有)
*   param:Object                 觸發事件時的參數(只有日誌類型爲'publish'的纔有)
* }]
* eventCenter = {
*   eventName:[Function,Function]  //eventName即爲事件名,其值爲訂閱方法列表
* }
* .subscribe(eventName, fun)        訂閱  eventName:事件名 fun:訂閱方法
* .unsubscribe(eventName, fun)      取訂  eventName:事件名 fun:訂閱方法
* .publish(eventName[,param])       發佈  eventName:事件名 param:事件參數
* .showLog([filter])                日誌展現 filter 過濾器,同數組的過濾器用法 返回過濾後的log
* .showEventCenter([eventName])     事件中心 eventName 事件名 返回事件綁定的方法
* */
let subscribeCenter = function () {
  //事件中心
  let eventCenter = {};
  //日誌
  let log = [];

  //添加日誌函數
  function pushLog(type, eventName, fun, param) {
    let info = {
      index: log.length,
      type: type,
      eventName: eventName,
      time: new Date()
    };
    if (fun) {
      info.fun = fun;
    }
    if (param) {
      info.param = param;
    }
    log.push(info)
  }

  return {
    //訂閱
    subscribe(eventName, fun) {
      pushLog("subscribe", eventName, fun);
      eventCenter[eventName] = eventCenter[eventName] || [];
      eventCenter[eventName].push(fun);
    },
    //取消訂閱
    unsubscribe(eventName, fun) {
      pushLog("unsubscribe", eventName, fun);
      let onList = eventCenter[eventName];
      if (onList) {
        for (let i = 0; i < onList.length; i++) {
          if (onList[i] === fun) {
            onList.splice(i, 1);
            return
          }
        }
      }
    },
    //發佈
    publish(eventName, param) {
      pushLog("publish", eventName, null, param)
      let onList = eventCenter[eventName];
      if (onList) {
        for (let i = 0; i < onList.length; i++) {
          onList[i](param)
        }
      }
    },
    //顯示日誌
    showLog(filter) {
      filter = filter || (() => true);
      let returnLog = log.filter(filter);
      returnLog.forEach(x => {
        let y = {};
        for (let key in x) {
          y[key] = x[key]
        }
        return y
      });
      return returnLog;
    },
    //顯示事件中心
    showEventCenter(eventName) {
      let selectEM = eventName ? eventCenter[eventName] : eventCenter, returnEM = {};
      for (let key in selectEM) {
        returnEM[key] = [];
        selectEM[key].forEach(x => {
          returnEM[key].push(x)
        });
      }
      return returnEM
    }
  }
}();

若是有看我上一篇文章中事件監聽實現的朋友應該對這個不部分代碼有一種熟悉的感受,確實事件監聽和發佈訂閱的實現很是的像。我主要多作的就是一個日誌的拓展,保證了每次的動做均可以被監聽和查看;java

發佈中心API

這個在上面是有的,可是由於上面的部分有一些同窗是不看的,因此就在這裏摘出來,方便這些同窗瞭解發佈中心的用法設計模式

/*
* log=[{
*   index: Number,                日誌編號(自增)
*   type: String,                 日誌類型('subscribe','unsubscribe','publish')
*   eventName: String,            事件名
*   time: new Date(),             時間
*   fun:Function                 訂閱/取訂的方法(只有日誌類型爲'subscribe'或'unsubscribe'的纔有)
*   param:Object                 觸發事件時的參數(只有日誌類型爲'publish'的纔有)
* }]
* eventCenter = {
*   eventName:[Function,Function]  //eventName即爲事件名,其值爲訂閱方法列表
* }
* .subscribe(eventName, fun)        訂閱  eventName:事件名 fun:訂閱方法
* .unsubscribe(eventName, fun)      取訂  eventName:事件名 fun:訂閱方法
* .publish(eventName[,param])       發佈  eventName:事件名 param:事件參數
* .showLog([filter])                日誌展現 filter 過濾器,同數組的過濾器用法 返回過濾後的log
* .showEventCenter([eventName])     事件中心 eventName 事件名 返回事件綁定的方法
* */

發佈/訂閱模式在異步中的應用

這裏是重點,須要你們仔細看,理解了這段代碼不光能夠解決異步問題,還能夠理解發布訂閱者模式是如何應用的;數組

//發佈者
let f1 = function () {
  setTimeout(function () {
    console.log("'done' 事件發佈 參數:", 123);
    subscribeCenter.publish("done", 123);
    console.log("事件中心", subscribeCenter.showEventCenter());
    console.log("f3 取訂 'done'");
    subscribeCenter.unsubscribe("done", f3);
    setTimeout(function () {
      console.log("'done' 事件發佈 參數:", 233);
      subscribeCenter.publish("done", 233);
      console.log("事件中心", subscribeCenter.showEventCenter());
      console.log("日誌", subscribeCenter.showLog());
    }, 100)
  }, 100)
};
//訂閱者
let f2 = function (param) {
  console.log("f2 is running, param is", param);
};
//訂閱者
let f3 = function (param) {
  console.log("f3 is running, param is", param)
};

//訂閱
console.log("f2 訂閱 'done'");
subscribeCenter.subscribe("done", f2);
console.log("f3 訂閱 'done'");
subscribeCenter.subscribe("done", f3);
//發佈
f1();

先貼運行結果
運行結果
在這裏能夠看到,該模式與事件監聽模式很是類似,可是全部的發佈都經過了同一個發佈中心來控制,這樣的話能夠方便咱們追蹤整個事件的狀態;異步

相關文章
相關標籤/搜索