forkJoin
用forkJoin合並的流,會在每個被合並的流都發出結束信號時發射一次也是唯一一次數據。 即所有的流都complete或者error時才會發射一次數據。
zip
zip工作原理如下,當每個傳入zip的流都發射完畢第一次數據時,zip將這些數據合並為數組並發射出去;當這些流都發射完第二次數據時,zip再次將它們合並為數組並發射。以此類推直到其中某個流發出結束信號,整個被合並后的流結束,不再發射數據。
zip和forkJoin的區別在於,forkJoin僅會合並各個子流最后發射的一次數據,觸發一次回調;zip會等待每個子流都發射完一次數據然后合並發射,之后繼續等待,直到其中某個流結束(因為此時不能使合並的數據包含每個子流的數據)。
combineLatest
combineLatest與zip很相似,combineLatest一開始也會等待每個子流都發射完一次數據,但是在合並時,如果子流1在等待其他流發射數據期間又發射了新數據,則使用子流最新發射的數據進行合並,之后每當有某個流發射新數據,不再等待其他流同步發射數據,而是使用其他流之前的最近一次數據進行合並。
concat
按照順序,前一個 observable 完成(complete)了再訂閱下一個 observable 並發出值 。即前一個observable發出complete信號后,才會訂閱下一個observable。
merge
merge 把多個 observable 同時處處理, 當多個 observable 其中一個被觸發時都可以被處理,這很常用在一個以上的按鈕具有部分相同的行為。
例如一個影片播放器有兩個按鈕,一個是暫停(II),另一個是結束播放(口)。這兩個按鈕都具有相同的行為就是影片會被停止,只是結束播放會讓影片回到 00 秒,這時我們就可以把這兩個按鈕的事件 merge 起來處理影片暫停這件事。
concatAll、mergeAll、switchAll屬於高階 Observable 的 操作符。都是用來打平Observable的。
所謂的 Higher Order Observable 就是指一個 Observable 發送出的元素還是一個 Observable,就像是二維數組一樣,一個數組中的每個元素還是數組。
如果用TypeScript中的泛型來表達就像是Observable<Observable<T>>,通常我們需要的是第二層 Observable 送出的元素,所以我們希望可以把二維的 Observable 改成一維的,像是下面這樣 Observable<Observable<T>> => Observable<T>
concatAll
處理完前一個 observable 才會在處理下一個 observable。依次按順序執行一個個observable 。
switchAll
新的 observable 送出后直接處理新的 observable 不管前一個 observable 是否完成,每當有新的 observable 送出就會直接把舊的 observable 退訂(unsubscribe),永遠只處理最新的 observable!
mergeAll
並且能夠同時並行處理所有的 observable 。
看下面的例子,我們可以切換為 concatAll,mergeAll,switchAll 體驗區別
const example = fromEvent(document.body, 'click')
.pipe(
// map 把送出的event事件轉換為 Observable
// 每次點擊送出一個新的 Observable
map(e => {
// console.log(e);
// 生成新的 Observable,點擊一次輸出0,1,2
return interval(1000).pipe(take(3))
}),
// concatAll 比如快速點擊三次,會按順序輸出三次0,1,2
// switchAll 快速點擊,只輸出一次0,1,2,也就是說老的舍去只保留最新的
// mergeAll 快速點擊,會重復的輸出多次0,1等。點擊越多下,最后送出的頻率就會越快。不會舍去,每次都會輸出
switchAll()
);
example.subscribe({
next: (value) => { console.log(value); },
error: (err) => { console.log('Error: ' + err); },
complete: () => { console.log('complete'); }
});
