iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 5
0
Modern Web

ngrx/store 4 學習筆記系列 第 5

[ngrx/store -5] 高階 (High Order) Observable

高階 (High Order) Observable

High Obser Observable

在 Javascript 中,陣列中除了純量(number, string...) 外,也可以有陣列,在物件中也可以有物件,那 Observable 觀察的資料流當然也可以是一些 Observables. 這樣的 Observable 我們稱為高階 (High Order) Observable, 舉個例子

const numObservable = new Rx.Observable.create(observer => {
  observer.next(1);
  setTimeout(() => observer.next(3), 2000);
  setTimeout(() => observer.next(5), 3000);
});

const highObservable = numObservable.map(v => Rx.Observable.of(v*10));

highObservable
  .subscribe(
    x => x.subscribe(
      y => console.log("from inner: ", y)
      )
  );

會簡單印出from inner: 10, from inner: 30, from inner: 50

  1. 第一個 numObservable 又稱為 outer Observable,它先觸發一個 1,兩秒後觸發 3, 第三秒觸發 5.
  2. 當 outer Observable 發出新資料時,會丟到 inner Observable Rx.Observable.of(v*10),將產生新的資料乘 10
  3. 所以當 subscribe 時會有兩個 subscribe, 第一個是外圈 outer Observable 的 subscribe, 第二個才是內圈的 subscribe
  4. 這樣做當然有點麻煩,所以有一些 Operator 可以幫助我們簡化這個 subscribe,例如
const numObservable = new Rx.Observable.create(observer => {
  observer.next(1);
  setTimeout(() => observer.next(3), 2000);
  setTimeout(() => observer.next(5), 3000);
});

numObservable.mergeMap(v => Rx.Observable.of(v*10))
            .subscribe(x => console.log("from mergeMap: ",x));

跟上面的結果會是一樣的,當然這些強大的 Operator 功能不只如此,我們來介紹第一個 Operator

mergeMap (flatMap)

上面的例子中 outer Observable 觸發三次,所以會產生三個 inner Observable, mergeMap 或者以前稱為 flatMap 的意思就是將這些 inner Observables 結合在一起,或者說將它們攤平(flat) 產生一個新的 Observable, 再舉一個例子

const numObservable = new Rx.Observable.create(observer => {
  observer.next(1);
  setTimeout(() => observer.next(3), 2000);
  setTimeout(() => observer.next(5), 3000);
});

numObservable.mergeMap(v => Rx.Observable.interval(500).take(3), (v, i) => v * 10)
.subscribe(x => console.log("from mergeMap: ", x));

它會印出
https://ithelp.ithome.com.tw/upload/images/20171221/20103574v4fCgL7Nis.png
簡單說明一下

  1. numObservable 跟上面一樣
  2. inner Observable 收到資料後,會半秒鐘會觸發一次動作,總共做 3 次
  3. mergeMap 的第二個參數是一個函數, 可以帶 Outer 跟 inner Obervable 的值再加工,這裡我們將 Outer Observable 的值乘 10
  4. 注意到當第一個 50 產生後,前面的最後一個 30 因為時間差才印出來

switchMap

switchMap 跟 mergeMap 一樣將 inner Observables 結合成一個新的 Observable,但是在 Outer Observable 觸發新的資料後,原先的 inner Observable 就會被 cancel 掉,看以下的例子

const numObservable = new Rx.Observable.create(observer => {
  observer.next(1);
  setTimeout(() => observer.next(3), 2000);
  setTimeout(() => observer.next(5), 3000);
});

numObservable.switchMap(v => Rx.Observable.interval(500).take(3), (v, i) => v * 10)
.subscribe(x => console.log("from switchMap: ", x));

結果會是
https://ithelp.ithome.com.tw/upload/images/20171221/20103574AMiQ74h1cv.png
這裡的 Outer Observable 跟 Inner Observable 都跟 mergeMap 一樣,但在印出第一個 30 後就開始印 50,而後面兩個 30 就被丟掉了

concatMap

最後當然有 concatMap, 就像 concat 一樣,他會很有紀律的依次做完每一個 inner Observable

const numObservable = new Rx.Observable.create(observer => {
  observer.next(1);
  setTimeout(() => observer.next(3), 2000);
  setTimeout(() => observer.next(5), 3000);
});

numObservable.concatMap(v => Rx.Observable.interval(500).take(3), (v, i) => v * 10)
.subscribe(x => console.log("from concatMap: ", x));

會完整且依序印出
https://ithelp.ithome.com.tw/upload/images/20171221/20103574xxgSHFxmhv.png

以上的例子,請參考 codepen

這些 High Order Operator 對 ngrx/store 很重要,特別是在做 effect 時,我們通常要透過 Angular 的 HttpClient 來接後端的資料。而 HttpClient 回傳的就是一個 Observable. 所以當一個 Store 的 Action (也是 Observable) 要處理 HttpClient (Observable)時,就會用到這些 Operator.

還有這些 High Order Operator 的 inner Observable 也可以是 Promise,所以才說這些是強大的 Operator 群。

ngrx/store 代表了三個主題, ng 是 Angular, rx 是 RxJS, 也就是這幾天談的 Observable 的部分,接下來,讓我們來仔細看一下 store 的部分,也就是 Flux(Redux) 的基礎介紹


上一篇
[ngrx/store - 4] 多重資料流的 Operators
下一篇
[ngrx/store-6] Flux 的基本概念
系列文
ngrx/store 4 學習筆記30

尚未有邦友留言

立即登入留言