[RxJS] 過濾類型 Operators (2) - take / takeLast / takeUntil / takeWhile

|

今天來介紹 take 系列的各種過濾類型 operators。

take

take 代表要從來源 Observable 中觸發 N 次事件的值;當訂閱開始後,如果發生過的事件數量已經達到我們設定的數量後,就會結束;在前面我們也稍微介紹過,並不困難:

timer(0, 1000).pipe(
  take(6)
).subscribe({
  next: data => console.log(`take 示範: ${data}`),
  complete: () => console.log(`take 結束`),
});
// take 示範: 0
// take 示範: 1
// take 示範: 2
// take 示範: 3
// take 示範: 4
// take 示範: 5
// take 結束

彈珠圖:

0---1---2---3---4---5---6---7---8---...
take(6)
0---1---2---3---4---(5|)

程式碼:https://stackblitz.com/edit/mastering-rxjs-operator-take

takeLast

take 是從事件開始時抓取前面 N 次的事件值,而 takeLast 則是從抓取 Observable 最後 N 次的事件值,因次 takeLast 會等到 Observable 結束後,才會得到最後幾次事件的資料。

range(1, 5).pipe(
  takeLast(3)
).subscribe(
  data => console.log(`takeLast 示範: ${data}`)
);
// takeLast 示範: 3
// takeLast 示範: 4
// takeLast 示範: 5

彈珠圖:

(12345)
takeLast(3)
  (345)

程式碼:https://stackblitz.com/edit/mastering-rxjs-operator-takelast

takeUntil

takeUntil 會持續觸發來源 Observable 的事件值,直到 (until) 指定的另外一個 Observable 發生新事件時,才會結束,算是蠻常用的一個 operator。

const click$ = fromEvent(document.querySelector('#btnStop'), 'click'); 
const source$ = interval(1000).pipe(map(data => data + 1))

source$.pipe(
  takeUntil(click$)
).subscribe({
  next: data => console.log(`takeUntil 示範: ${data}`),
  complete: () => console.log('takeUntil 結束')
});
// takeUntil 示範: 1
// takeUntil 示範: 2
// takeUntil 示範: 3
// takeUntil 示範: 4
// takeUntil 示範: 5
// (click$ 發出新事件)
// takeUntil 結束

彈珠圖:

          ---1---2---3---4---5---6-...
takeUntil(---------------------c---...)
          ---1---2---3---4---5-|

可以看到訂閱後在 click$ 事件發生前,會持續觸發 source$ 的事件,直到 click$ 發生事件,就結束整個 Observable。

程式碼:https://stackblitz.com/edit/mastering-rxjs-operator-takeuntil

takeWhile

takeWhile 內需要傳入一個 callback function,這個 callback function 決定 takeWhile 發生事件的時機,只要事件值持續符合 callback function 內的條件,就會持續產生事件,直到不符合條件後結束。

const source$ = interval(1000).pipe(map(data => data + 1))

source$.pipe(
  takeWhile(data => data < 5)
).subscribe({
  next: data => console.log(`takeWhile 示範 (1): ${data}`),
  complete: () => console.log('takeWhile 結束 (1)')
});

// takeWhile 示範 (1): 1
// takeWhile 示範 (1): 2
// takeWhile 示範 (1): 3
// takeWhile 示範 (1): 4
// takeWhile 結束 (1)

彈珠圖:

---1---2---3---4---5---6---7....
takeWhile(data => data < 5)
---1---2---3---4---|
                   ^ 不符合條件了,結束

程式碼:https://stackblitz.com/edit/mastering-rxjs-operator-takewhile

takeWhile 的 callback 可以傳入事件值 (value) 及索引值 (index);除了 callback function 之外,還有一個 inclusive 參數,代表是否要包含判斷不符合條件的那個值,預設為 false,當設為 true 時,發生結束條件的那次事件值也會被包含在要發生的事件內。

source$.pipe(
  takeWhile(data => data < 5, true)
).subscribe({
  next: data => console.log(`takeWhile 示範 (2): ${data}`),
  complete: () => console.log('takeWhile 結束 (2)')
});

// takeWhile 示範 (2): 1
// takeWhile 示範 (2): 2
// takeWhile 示範 (2): 3
// takeWhile 示範 (2): 4
// takeWhile 示範 (2): 5
// takeWhile 結束 (2)

本日小節

take 系列的 operators 都是決定來源 Observable 的事件可以發生多少次的方法,但各有不同使用情境:

  • take:代表要讓前 N 次事件可以發生,符合數量後結束目前的 Observable。
  • takeLast:代表要讓後 N 次事件可以發生,因此需要來源 Observable 結束。
  • takeUntil:會持續讓來源 Observable 事件發生,直到指定的另一個 Observable 發生新事件了,結束目前的 Observable。
  • takeWhile:可以判斷資料是否符合條件,只要資料符合條件,事件就會持續發生,當資料不符合條件,目前的 Observable 就會結束。

take 本身是「拿資料」的意思,明天會介紹另外一組剛好相反,有著「忽略資料」意思的 skip 系列 operators。

相關資源

如果您覺得我的文章有幫助,歡迎免費成為 LikeCoin 會員,幫我的文章拍手 5 次表示支持!