fromEvent(this.test, 'click').subscribe((event) => console.log(event));
this.test 的賦值邏輯:typescript
this.test = this.document.getElementById('test');
每當該 id 爲 test 的按鈕被點擊一次,則 fromEvent issue 一個新的值,內容爲 MouseClick 事件:函數
本文介紹這個神奇的 fromEvent 的工做原理。this
在 rxjs/_esm2015/index.js 下能看到全部 rxjs 支持的 operators:
spa
fromEvent 構造函數支持最多 4 個輸入參數,但個人例子裏,之傳入了兩個。所以直接進入 Observable 對象的構造邏輯:code
Observable 的構造函數,只有一個輸入參數,該輸入參數爲一個函數。這個函數是一個匿名函數,只有函數體而無函數名稱。server
把該匿名函數維護在 Observable 的私有屬性 _subscribe 裏。
對象
fromEvent 返回一個可觀察對象,調用該對象的 subscribe 方法,給其註冊觀察者。rxjs
上圖 observerOrNext 就是咱們應用程序裏,傳入給 subscribe 方法的匿名函數,即便用 console.log 打印 id 爲 test 的 button 被點擊以後拋出的 MouseEvent 事件。事件
由於咱們暫時沒有給 fromEvent 返回的 Observable 對象指定 operator,所以第 20 行 operator 爲 undefined:ip
調用函數 toSubscriber 建立一個新的 subscriber:
上圖 nextOrObserver 就是我應用程序裏指定的 console.log(event) 匿名函數,只是用 Subscriber 包了一層。
Subscriber.js 內部:Subscriber 的 destination 屬性,指向了 SafeSubscriber 實例:
再回到 Observable 的 subscribe 方法。如今咱們知道了,在其 toSubscriber 方法裏,建立了一個 Subscriber 實例,其重要屬性如上圖1,2,3所示。由於沒有爲該 Observable 指定 operator,因此第 22 行的 IF 分支進不去,而是執行第 26 行的 else 分支。
進入 trySubscribe 方法:
_trySubscribe 是 _subscribe 方法的包裹,再加上錯誤處理:
文章開頭提到的 Observable 私有屬性 _subscribe, 指向 fromEvent.js 第14行匿名函數:
如今執行該匿名函數,函數體內 setupSubscription.
如何判斷傳進來的變量是 EventTarget 呢?
檢查其是否具備 addEventListner 和 removeEventListener 便可。
這裏把 fromEvent.js 裏某個 handler 函數,做爲按鈕點擊後的事件處理函數進行註冊。
注意,這裏給 click 點擊事件註冊的,並非咱們應用程序指定的 console.log(event), 而是 fromEvent.js 裏一個內部函數,以下圖所示:
當我點擊 UI 的 test 按鈕後,觸發 click 事件,fromEvent.js 裏定義的事件處理函數被調用:
還記得咱們以前提到的 toSubscriber 函數調用麼?將應用程序定義的 console.log(event), 包裝成 SafeSubscriber,存儲到 _next 屬性裏。
這裏,最終觸發 subscriber 的私有屬性 _next 指向的應用程序處理邏輯:
使用了 JavaScript function 原生的 call 方法進行調用:
最終,進入了應用程序打印代碼執行,謎底就此解開:
更多Jerry的原創文章,盡在:"汪子熙":