參考?EventEmitter實現一個簡單的訂閱發(fā)布功能函數
目的
訂閱發(fā)布模式 應該是 JS 最常用的設計模式,也可稱之為 觀察者模式,前端各個方面都會涉及到它,比如:瀏覽器中的事件監(jiān)聽機制、nodejs
中的 EventEmitter
、redux 數據傳遞實現等等。
不管是 瀏覽器中的事件監(jiān)聽機制 還是 nodejs
中的 EventEmitter
,都只能在各自的環(huán)境進行運行。因此我們需要用一份代碼來讓多端都可以調用,EventEmitter
功能更全面,我們借鑒它來實現一個完整的 PubSub
。
實現
主要參考 EventEmitter 的功能來,本篇文章提供 簡單實現,下一篇提供了 完整實現,點擊即可去查看,代碼有問題歡迎評論區(qū)指出。
實現常用功能:
on
: 用于添加訂閱off
: 用于取消訂閱once
: 用于添加一次性訂閱emit
: 用于發(fā)布事件,讓訂閱者收到通知
完整代碼實現:
type Listener = (...args: any[]) => void; type EventInfo = { // 監(jiān)聽器 listener: Listener; // 備份,需要改變 listener 時,則需要備份,比如 once bak?: Listener; }; // 創(chuàng)建一次性監(jiān)聽器 function createOnceListener(pub: PubSub, eventName: string | symbol, listener: Listener) { const onceListener = (...args: any[]) => { // 執(zhí)行一次后直接取消訂閱 listener(...args); pub.off(eventName, listener); }; return onceListener; } export class PubSub { private eventMap: Record<string | symbol, EventInfo[]> = {}; // 訂閱 on = (eventName: string | symbol, listener: Listener) => { if (!this.eventMap[eventName]) { this.eventMap[eventName] = []; } this.eventMap[eventName].push({ listener }); return this; }; // 取消訂閱 off = (eventName: string | symbol, listener: Listener) => { if (this.eventMap[eventName]) { this.eventMap[eventName] = this.eventMap[eventName].filter((item) => { // once listener 取消訂閱 if (item.bak) { return item.bak !== listener; } // 正常 listener 取消訂閱 return item.listener !== listener; }); } return this; }; // 類似 EventEmitter 中的 emit 函數 emit = (eventName: string | symbol, ...args: any[]) => { this.eventMap[eventName]?.forEach((item) => { item.listener(...args); }); return this; }; // 只訂閱一次 once = (eventName: string | symbol, listener: Listener) => { const onceListener = createOnceListener(this, eventName, listener); this.on(eventName, onceListener); return this; }; } // 不需要有全局訂閱功能的,可以去掉這個 export const pubSub = new PubSub();
實現說明:
- 不管訂閱還是發(fā)布的時候都需要判讀是否有已存在的隊列。
eventMap
用于存儲訂閱相關信息。once
使用createOnceListener
函數實現,給原listener
添加一層包裹,執(zhí)行一次后自動注銷。off
注銷監(jiān)聽時需要考慮once
的listener
被添加了一層包裹,需要用備份的原始listener
來判斷。listener
函數需要考慮有多個參數。- 操作性的函數的返回值為
this
,用于鏈式調用,比如pubSub.emit("test").off("test")
總結
實現過程是通過閱讀 EventEmitter
官方文檔的 API 來進行反向實現的,typescript
類型可以直接通過 nodejs
使用的時候獲取,這也一般是想實現某一個功能的方法。
有不對的地方歡迎指出,感謝??。
點擊查看下一篇 完整實現。
以上就是參考 EventEmitter實現一個簡單的訂閱發(fā)布功能函數的詳細內容,更多關于EventEmitter訂閱發(fā)布功能函數的資料請關注腳本之家其它相關文章!
相關文章
windows系統(tǒng)上完全卸載并重裝Node的步驟(親測可用)
對于Windows平臺來說,所有的應用程序,其安裝卸載都是一樣的,node.js也不例外,但是還是很多用戶不明白,下面這篇文章主要給大家介紹了關于windows系統(tǒng)上完全卸載并重裝Node的步驟,需要的朋友可以參考下2023-03-03使用Express+Node.js對mysql進行增改查操作?
這篇文章主要介紹了使用Express+Node.js對mysql進行增改查操作,文章圍繞主題展開詳細的內容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-08-08Node.js v8.0.0正式發(fā)布!看看帶來了哪些主要新特性
Node.js v8.0.0 已正式發(fā)布。v8.0.0 是下一個主要的版本,帶來了一系列重大的變化和新功能,內容十分多!下面這篇文章主要帶著大家一起看看Node.js v8.0.0帶來了哪些主要新特性,需要的朋友可以參考借鑒,下面來一起看看吧。2017-06-06