rxjs Observable filter Operator 的實現原理介紹

注销發表於2022-05-24

看下面這段使用 filter Operator 的程式碼:

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

import { filter } from 'rxjs/operators';

function filterKey(key) {
  console.log('input: ', key);
  const result: MonoTypeOperatorFunction<KeyboardEvent> = filter(
    (event: KeyboardEvent) => {
      console.log('input event: ', event);
      return event.key === key;
    }
  );
  console.log('result: ', result);
  return result;
}

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

原始 Observable 呼叫 pipe,執行自定義 Operator 的邏輯,在邏輯裡生成一個 filter Operator 例項。單步除錯如下:

返回一個 filterOperatorFunction:

filter 呼叫返回的是一個 filterOperatorFunction:

至此我們只完成了 pipe 兩段呼叫的第一段:得到 filter 返回的 filterOperatorFunction.

然後執行 pipe 操作的第二段,如上圖圖例所示,將原始 Observable 傳入 filterOperatorFunction:

這個第二段操作,就會建立新的 FilterOperator 例項,在 lift 操作裡,新建一個 Observable,然後把原始的 Observable 設定為這個新 Observable 例項的 source 欄位,將 FilterOperator 例項賦給原始 Observable 的 Operator 欄位。

pipe 呼叫執行的結果,返回一個新的 Observable 給 pipe 的呼叫者。最後我們 subscribe 的,就是這個 pipe 返回的 Observable.

subscribe 內部,this 就是 pipe 返回的新 Observable,operator 指向 filterOperator,source 指向 fromEvent 返回的原始 Observable:

首先利用 TypeScript 物件結構語法,object destructing,將 this.operator 欄位賦給變數 Operator,然後以原始 Observable 作為上下文,呼叫 filter Operator.

這樣,pipe 返回的 Observable 上進行訂閱,會傳遞到原始 Observable 的 subscribe 操作:

當我們在鍵盤上隨便敲擊一個字元後,觸發 MouseEvent 對應的 handler,在 handler 裡呼叫 Observer 的 next 操作。

next 操作最後會觸發 filtersubscriber predicate 屬性即應用開發人員傳入 filter Operator 的匿名函式:

filter 輸入引數也是一個函式,該函式的輸入即 MouseEvent:

fromEvent 新建的 Observable,其實現邏輯內部,同樣呼叫了 subscriber 的 next 方法來發射值。同時 fromEvent 返回的 Observable 同其他建立運算子比如 of 的特色之處,就在於其能夠響應各種事件,比如 document 的 keyup 事件。

這種事件序號產生器制,是在上圖 setupSubscription 函式里實現的。

註冊的具體實現,採取了瀏覽器原生提供的 addEventListener,呼叫者為 document 全域性物件,傳入的 eventName 為 keyup,handler 即 fromEvent 內部實現,即上圖綠色高亮區域內的程式碼。

export declare function filter<T>(predicate: (value: T, index: number) => boolean, thisArg?: any): MonoTypeOperatorFunction<T>;

filter Operator 接受一個 predicate 作為輸入引數,返回一個型別為 MonoTypeOperatorFunction 的函式。

這裡的 T 為型別引數。MonoType 對應 T,意思是單引數。

MonoTypeOperatorFunction 是一種特殊的 OperatorFunction,當後者的輸入和返回引數都相同時,即特殊化為單型別 OperatorFunction:

OperatorFunction 又是一種特殊的 UnaryFunction(一元函式),當一元函式的輸入和輸出型別都是一個 Observable 時,即特殊化成了 OperatorFunction.

相關文章