rxjs Observable 自定義 Operator 的開發技巧

注销發表於2022-05-24

運算子是 RxJS 庫和 Observables 的基礎塊。 它使我們能夠透過使用一些關鍵字(函式)來執行復雜的操作。 運算子只不過是獲取源 Observable、對其執行操作並返回新 Observable 的函式。

rxJS 的 管道運算子 pipe 允許我們連結運算子。每個運算子都接受一個 Observable 並返回一個 Observable,這種一致的行為使得連結成為了可能。 Operator 返回的 Observable 作為下一個運算子的輸入。

下面是一個最簡單的自定義 Operator 的例子。

import { interval, of } from 'rxjs';

function fancyOperator(source) {
  return source;
}

interval(1000)
  .pipe(fancyOperator)
  .subscribe((value) => console.log(value));

pipe 呼叫並不會真正執行 Operator 函式體的邏輯,直至 Observable 被 subscribe 為止??是這樣嗎?

pipeFromArray 僅僅取出 Operation 陣列裡儲存的第一個函式。

然後呼叫之,輸入引數 this 就是源 Observable.

下面我們對 fancyOperator 新增少許功能。

import { interval, Observable } from 'rxjs';

function fancyOperator(source) {
  return Observable.create((observer) => {
    observer.next('Jerry');
    observer.complete();
  });
}

interval(1000)
  .pipe(fancyOperator)
  .subscribe((value) => console.log(value));

這裡我們採取了移花接木的方法,在自定義 Operator 裡返回了一個新的 Observable,這個 Observable 只發射一次資料,就進入終止狀態。

看一個現實專案中自定義 Observable 的例子:

import { fromEvent, interval, Observable } from 'rxjs';

import { filter } from 'rxjs/operators';

function filterKey(key) {
  return filter((event: KeyboardEvent) => event.key === key);
}

fromEvent(document, 'keyup')
  .pipe(filterKey('Enter'))
  .subscribe(
    (data) => console.log(data) // KeyboardEvent
  );

這個自定義 Operator 的輸入是 Enter,輸出是 filter 呼叫的返回值,一個新的函式。filter 呼叫接收一個 predicate,返回一個新的函式。

看一下 filter 返回函式執行時列印的值:

把原始的 Observable,傳送給 filter 返回的函式並執行:

filter 返回的函式對原始 Observable 進行加工,返回一個新的 Observable:

觸發 filterOperator 的建構函式:

把新建的 filterOperator 例項傳入原始 Observable 的 lift 方法。這個 lift 操作非常簡單,新建一個 Observable,把原始的 Observable掛接到新的 Observable 的 source 欄位,同時把 Operator 例項賦給新的 Observable 例項的 operator 方法。

因此最後訂閱時,訂閱的是 lift 操作之後的新的 Observable 例項。

subscribe 會觸發 filterOperator 的 call 方法:

相關文章