在 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
,兩秒後觸發 3
, 第三秒觸發 5
.Rx.Observable.of(v*10)
,將產生新的資料乘 10const 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
上面的例子中 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));
它會印出
簡單說明一下
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));
結果會是
這裡的 Outer Observable 跟 Inner Observable 都跟 mergeMap 一樣,但在印出第一個 30 後就開始印 50,而後面兩個 30 就被丟掉了
最後當然有 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));
會完整且依序印出
以上的例子,請參考 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) 的基礎介紹