js實現對主題的訂閱(topic訂閱),內附源碼

有不合理和錯誤的地方歡迎小夥伴雅正,與大家共勉

理解對主題訂閱

angular中的訂閱的實現是用的RX.js庫,我們可以用Subject來實現事件的訂閱和發佈

// 聲明一個可觀察對象
const obervable = new Subject();
// 訂閱
observable.subscript( data => {
    handler...
})
// 發佈
observable.next(data)

項目中離不了對同一個可觀察對象的不同主題的訂閱,比如單頁面應用中某個負責權限的可觀察對象,進行登錄和登出這兩個主題進行訂閱,這個可觀察會根據用戶的登錄和登出去訂閱者發佈登錄和登出的事件,讓訂閱者去執行異形系列的操作(大型項目中這有利於降低功能間的耦合)

// 聲明一個可觀察對象,也是一個事件發佈對象
const obervable = new Events();
// 對某個話題訂閱
obervable.subscript("login",handler)
obervable.subscript("logout",handler)
// 對某個主題發佈實踐
observable.publish("login",data)
observable.publish("logout",data)

給大家看個熟悉的,jQuery的on方法,方便小夥伴理解

// 選取一個dom元素
const dom = $("#obervableDom")
// 對這個dom元素的主題進行訂閱(事件監聽)
dom.on("click",handler)
// dom元素髮布主題(觸發事件)
dom.click()

熟悉ionic的小夥伴可能有話說了,這不就是ionic的Events嗎。這就是ionic的Events,不過想不明白RX.js這麼優秀的一個庫怎麼會沒有實現對主題的訂閱這個功能呢,是不是RX.js中有替代方法,有小夥伴知道的話歡迎給我說一下,不勝感激。

下面是我根據ionic Events類的思路和代碼重寫的一個新的Events,用了一些ES6的語法。用法文檔沒有變化(😁😁😁😁😁我也感覺我是在抄襲了,就當給小夥伴推廣Ionic 的Events了)

實例方法文檔

publish(topic, eventData)

對某個主題發佈數據,觸發對某個主題訂閱的回調函數
| 參數 |類型|備註|
topic string 要發佈的主題名稱
eventData any 發送給訂閱此主題的事件(函數)的數據

subscribe(topic, handler)

對某個主題進行訂閱,發佈該主題的事件時,會出發handler回調函數,handler的形參就是發佈主題給的數據
| 參數 |類型|備註|
topic string 要訂閱的主題名稱
handler function 處理髮布事件數據的回調函數

unsubscribe(topic, handler)

對某個主題取消訂閱,將不再處理該主題的發佈事件, 釋放內存
| 參數 |類型|備註|
topic string 要取消訂閱的主題名稱
handler function 要取消訂閱的處理函數

實例

// 聲明一個可觀察對象,也是一個事件發佈對象
const obervable = new Events();
// 對某個話題訂閱
obervable.subscript("topic1",handler)
obervable.subscript("topic2",handler)
// 對某個主題發佈實踐
observable.publish("topic1",data)
observable.publish("topic2",data)

源碼


export class NgEventsService {
  // 用來存儲訂閱主題和該主題的回調的函數 {topicName:[handlerfun]}
  private static channel;

  // 對某個主題進行訂閱,發佈該主題的事件時,會出發handler回調函數,handler的形參就是發佈主題給的數據
  subscribe(topic: string, ...handlers) {
    if (handlers.length === 0) {
      return;
    }
    if (!NgEventsService.channel[topic]) {
      NgEventsService.channel[topic] = [];
    }
    NgEventsService.channel[topic].push(...handlers);
  }
  // 對某個主題發佈數據,觸發對某個主題訂閱的回調函數
  publish(topic, ...handlers) {
    const channelTopic = NgEventsService.channel[topic];
    if (!channelTopic) {
      return null;
    }
    const responses = [];
    channelTopic.forEach(handler => {
      responses.push(handler.apply(0[0], handlers));
    });
    return responses;
  }
  // 對某個主題取消訂閱,將不再處理該主題的發佈事件
  unsubscribe(topic, handler) {
    const channelTopic = NgEventsService.channel[topic];
    if (!channelTopic) {
      return false;
    }
    if (!handler) {
      delete NgEventsService.channel[topic];
      return true;
    }
    const indexflag = channelTopic.indexOf(handler);
    if (indexflag < 0) {
      return false;
    }
    channelTopic.slice(indexflag, 1);
    if (channelTopic.length = 0) {
      delete NgEventsService.channel[topic];
    }
    return true;
  }
}

👍👍👍👍👍如果能幫助到小夥伴的話歡迎點個贊👍👍👍👍👍
👍👍👍👍👍如果能幫助到小夥伴的話歡迎點個贊👍👍👍👍👍

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章