使用typescript 寫一個簡單的事件監聽/發布訂閱模式的類


我們需要弄清楚,觀察者模式和發布訂閱模式是不一樣的,一張圖理解:

兩者區別:

  1. 觀察者 模式只有觀察者和被觀察者兩者,是松耦合

  2. 發布訂閱模式除了發布者和訂閱者外,還有一個調度中心,是解耦的,兩者沒有直接關系

  3. 觀察者主要是同步方式實現,二發布訂閱模式多數是異步實現,比如消息隊列

用typescript 簡單實現一個發布訂閱模式的類

 1 class byEvent {
 2     Events: { [key: string]: Array<Function> } //約束示例:{"eventName":[function(){},function(){},.....],......}
 3     constructor() {
 4         this.Events = {}
 5     }
 6     /**
 7      * 發布/ 觸發
 8      * @param eventName 
 9      * @param args 
10      */
11     emit(eventName: string, ...args: any) {
12         let callbackList = this.Events[eventName] || [];
13         callbackList.forEach(fn => fn.apply(this, args))
14         return this;
15         // 如果用js寫,遍歷的時候要做一下判斷是否是函數,ts 用類型約束,在調用或者編譯階段會檢測是否合法
16         // callbackList.map(fn=>{
17         //     if(typeof fn==="function") fn.apply(this,args)
18         // })
19     }
20     /**
21      * 訂閱/監聽
22      * @param eventName 
23      * @param callback 
24      */
25     on(eventName: string, callback?: Function) {
26         // if(!eventName||typeof eventName !=="string") return  ;// 因為用了ts 寫,所以這句不用寫了,如果是js寫,建議加這判斷
27         let callbackList = this.Events[eventName] || [];
28         callback && callbackList.push(callback)
29         this.Events[eventName] = callbackList
30         return this;
31 
32     }
33     /**
34      * 只訂閱一次/監聽一次:
35      * 思路:
36      * 1. 重新包裝一個回調函數(有名的),進行注冊訂閱/監聽,
37      * 2. 包裝函數里面直接調用 once方法的第二個參數回調函數,然后調用off方法 卸載該包裝函數
38      * @param eventName 
39      * @param callback 
40      */
41     once(eventName: string, callback?: Function) {
42         // if(!eventName||typeof eventName !=="string") return ;
43         let decor = (...args: any[]) => {
44             callback && callback.apply(this, args)
45             this.off(eventName, decor)
46         }
47         this.on(eventName, decor)
48         return this;
49 
50     }
51     /**
52      * 卸載/取消 某一個回調監聽(不是取消eventName的所有回調監聽),主要配合once一起,實例單獨調用,無意義
53      * @param eventName 
54      * @param callback 
55      */
56     off(eventName: string, callback: Function) {
57         let callbackList = this.Events[eventName] || [];
58         let resCallbacks = callbackList.filter(fn => fn !== callback)
59         this.Events[eventName] = resCallbacks
60         return this;
61 
62     }
63     /**
64      * 卸載/取消 指定eventName 的所有訂閱/監聽
65      * @param eventName 
66      * @param callback 
67      */
68     remove(eventName: string, callback?: Function) {
69         this.Events[eventName] = [];
70         callback && callback()
71         return this;
72 
73     }
74 
75 }
76 
77 // 使用示例
78 let o = new byEvent()
79 setInterval(() => {
80     o.emit("name", 123)
81     o.emit("name", 10, 20)
82     o.emit("post", { name: 1212 }, "post")
83 
84 }, 1000);
85 setTimeout(() => {
86     o.remove("name", function () {
87         console.log("remove")
88     })
89 }, 3000)
90 o.once("name", function (...res: any[]) {
91     console.log("once-name1", res)
92 })
93 o.on("name", function (...res: any[]) {
94     console.log("on-name2", res)
95 })
96 o.on("post", function (...res: any[]) {
97     console.log("on-post", res)
98 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM