昨天的文章中我們實際撰寫 JavaScript 用「觀察者模式」完成了一個「影片上架通知」的功能,今天我們就練習看看直接使用 RxJS 來完成一樣的功能,你會發現一切變得非常的簡單!
如同之前的練習,我們已經知道有一個被觀察的目標,這個目標資料變動時會通知所有的觀察者,我們可以直接建立一個 Subject 物件,作為被觀察的目標:
// 建立 youtuber$ subject (被觀察的目標)
const youtuber$ = new Subject();
一樣維持著我們習慣的命名風格,所有「可被觀察的」(Observable) 物件都會用邊樹名稱後面加個 $
符號的命名方式。
之後只要有影片上架,都可以透過 next()
方法將更新資料送出通知所有的觀察者
// 影片 1 上架,此時還沒有觀察者;只會顯示通知
youtuber$.next(1);
// 輸出結果:
// (沒有任何輸出)
當然,目前沒有任何觀察者加入,所以不會有任何結果。接著我們就來建立觀察者吧!
接著我們來實作觀察者,在 RxJS 內,每個觀察者都是一個實作 next()
、error()
和 complete()
方法的物件,分別來處理「資料變更」、「發生錯誤」和「串流完成」的行為;當然,如果某個行為沒有要處理,該方法可以直接不宣告。以我們例子來說,只要處理「資料變更」就好。
// 建立觀察者 A 物件
const observerA = {
next: id => {
console.log(`我是觀察者 A,我收到影片 ${id} 上架通知了`);
},
error: () => {}, // 沒有要處理「錯誤」的話不一定要加上這一行
complete: () => {} // 沒有要處理「完成」的話不一定要加上這一行
};
以觀察者模式來說,我們會說「把觀察者加入被通知的對象清單」;而在 RxJS 中,我更喜歡說成**「訂閱某個目標,把資料交給觀察者處理」**。
// 加入觀察者 A,也就是觀察者 A 開啟通知了
const observerASubscription = youtuber$.subscribe(observerA);
這個訂閱的動作,也會回傳一個 Subscription
訂閱物件,未來我們可以使用這個物件進行退訂動作。
以「影片上架通知」的例子來說,整個過程是一個「串流」,而每次影片上架都是一個新的「事件發生」,這個事件發生會及時通知所有的觀察者。所以在此時我們呼叫 youtuber$
這個 Subject 的 next()
方法,就會進入 observerA
的 next()
方法內的處理邏輯。
// 影片 2 上架,此時觀察者 A 會收到通知
youtuber$.next(2);
// 輸出結果:
// 我是觀察者 A,我收到影片 2 上架通知了
接著我們在建立一個觀察者,但用更簡單的寫法;由於不處理 error()
和 complete()
,我們不需要把完整的物件建立起來,只要準備好一個處理 next()
的方法放到訂閱參數裡面就好。
// 加入觀察者 B,也就是觀察者 B 開啟通知了
// 由於只處理 next,這裡就使用簡單的寫法,不另外建立物件
const observerBSubscription = youtuber$.subscribe(id => {
console.log(`我是觀察者 B,我收到影片 ${id} 上架通知了`);
});
由於現在有兩個觀察者了,所以當 youtuber$
有新的事件發生時,兩個觀察者都會收到通知:
// 影片 3 上架,此時觀察者 A 跟 B 都會收到通知
youtuber$.next(3);
// 輸出結果:
// 我是觀察者 A,我收到影片 3 上架通知了
// 我是觀察者 B,我收到影片 3 上架通知了
當呼叫 youtuber$
的 subscribe()
方法後,回會傳一個訂閱物件,我們可以透過此物件來決定何時要取消訂閱。
// 移除觀察者 B,也就是觀察者 B 關閉通知了
// 在 ReactiveX 中也稱為「取消訂閱」
observerBSubscription.unsubscribe();
上面的例子我們取消了觀察者 B 的訂閱,因此當 youtuber$
有新事件發生時,觀察者 B 就不會再次收到通知。
// 影片 4 上架,此時只剩下觀察者 A 會收到通知
youtuber$.next(4);
// 輸出結果:
// 我是觀察者 A,我收到影片 4 上架通知了
是不是很簡單啊!幫我們把觀察者模式基本的邏輯都包裝好了,省去自己設計的麻煩,雖然自己設計一個觀察者模式並不困難,但別忘了在 ReactiveX 還有 operators 啊!未來當我們介紹到 operators 後,就能更加體會整個 ReactiveX 為我們帶來的便利了!
今天的內容不長,主要是將觀察者的模式觀念帶入後,以 RxJS 的方式再練習一次,當我們一切都用 stream 和 observable 的視角去看待事情時,就會發現其中方便、好維護、好擴充的特性!
明天我們再來介紹 ReactiveX 實作的另一個模式 - 疊代器模式 Iterator Pattern。