iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 7
3
Modern Web

打通 RxJS 任督二脈系列 第 7

隨堂測驗 - 使用 RxJS 實作影片上架通知功能

昨天的文章中我們實際撰寫 JavaScript 用「觀察者模式」完成了一個「影片上架通知」的功能,今天我們就練習看看直接使用 RxJS 來完成一樣的功能,你會發現一切變得非常的簡單!

使用 RxJS 實作影片上架通知功能

步驟 1:建立被觀察的目標

如同之前的練習,我們已經知道有一個被觀察的目標,這個目標資料變動時會通知所有的觀察者,我們可以直接建立一個 Subject 物件,作為被觀察的目標:

// 建立 youtuber$ subject (被觀察的目標)
const youtuber$ = new Subject();

一樣維持著我們習慣的命名風格,所有「可被觀察的」(Observable) 物件都會用邊樹名稱後面加個 $ 符號的命名方式。

之後只要有影片上架,都可以透過 next() 方法將更新資料送出通知所有的觀察者

// 影片 1 上架,此時還沒有觀察者;只會顯示通知
youtuber$.next(1);
// 輸出結果:
// (沒有任何輸出)

當然,目前沒有任何觀察者加入,所以不會有任何結果。接著我們就來建立觀察者吧!

步驟 2:建立第一個觀察者

接著我們來實作觀察者,在 RxJS 內,每個觀察者都是一個實作 next()error()complete() 方法的物件,分別來處理「資料變更」、「發生錯誤」和「串流完成」的行為;當然,如果某個行為沒有要處理,該方法可以直接不宣告。以我們例子來說,只要處理「資料變更」就好。

// 建立觀察者 A 物件
const observerA = {
  next: id => {
    console.log(`我是觀察者 A,我收到影片 ${id} 上架通知了`);
  },
  error: () => {}, // 沒有要處理「錯誤」的話不一定要加上這一行
  complete: () => {} // 沒有要處理「完成」的話不一定要加上這一行
};

步驟 3:執行訂閱 (加入通知對象)

以觀察者模式來說,我們會說「把觀察者加入被通知的對象清單」;而在 RxJS 中,我更喜歡說成**「訂閱某個目標,把資料交給觀察者處理」**。

// 加入觀察者 A,也就是觀察者 A 開啟通知了
const observerASubscription = youtuber$.subscribe(observerA);

這個訂閱的動作,也會回傳一個 Subscription 訂閱物件,未來我們可以使用這個物件進行退訂動作。

步驟 4:送出新事件 (通知所有觀察者)

以「影片上架通知」的例子來說,整個過程是一個「串流」,而每次影片上架都是一個新的「事件發生」,這個事件發生會及時通知所有的觀察者。所以在此時我們呼叫 youtuber$ 這個 Subject 的 next() 方法,就會進入 observerAnext() 方法內的處理邏輯。

// 影片 2 上架,此時觀察者 A 會收到通知
youtuber$.next(2);
// 輸出結果:
// 我是觀察者 A,我收到影片 2 上架通知了

步驟 5:建立新的觀察者

接著我們在建立一個觀察者,但用更簡單的寫法;由於不處理 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 上架通知了

步驟 6:取消訂閱

當呼叫 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。


上一篇
觀察者模式 Observable Pattern 認識 RxJS
下一篇
從疊代器模式認識 RxJS
系列文
打通 RxJS 任督二脈35

尚未有邦友留言

立即登入留言