從一個實際的例子觸發,理解什麼是 Rxjs 的 defer 函式
我們在開發複雜的 Angular 應用時,經常會使用到 Rxjs 的 defer 函式,例如:
建立一個 Observable,在訂閱時呼叫 Observable 工廠為每個新的 Observer 建立一個 Observable 物件。
該函式接收一個輸入引數,型別為一個工廠函式。輸出為一個 Observable 物件,一旦被訂閱時,其繫結的工廠函式會被呼叫。
defer 的實質是延遲建立機制,即只有在返回的 Observable被訂閱時,才開始建立 Observable 物件。
defer 允許你只在 Observer 訂閱時建立一個 Observable。 它一直等到 Observer 訂閱它,呼叫給定的工廠函式來獲取一個 Observable —— 工廠函式通常會生成一個新的 Observable —— 並將 Observer 訂閱到這個 Observable。 如果工廠函式返回一個假值,則使用 EMPTY 作為 Observable 代替。 最後但並非最不重要的是,工廠函式呼叫期間的異常通過呼叫 error 傳遞給觀察者。
看下面這個具體的例子。
我們來單步除錯下上面這段程式碼。首先進入 defer 內部執行邏輯:
在 defer 內部,直接構造一個新的 Observable,並且將工廠函式傳入。該工廠函式在第8行被呼叫,用於生成一個包含應用程式業務邏輯的 Observable 物件,儲存在 input 裡。最後,將應用程式的subscriber 訂閱到這個工廠函式返回的 Observable 上。
我們再單步執行,發現程式執行流從上圖的第5行,跳轉到了 第16行。這體現了 defer 函式延遲建立 Observable 物件的行為。所謂延遲建立,準確的說,應該是延遲了包含業務邏輯的 Observable 物件的建立。
緊接著,回到我們的應用程式碼,此時針對 defer 函式返回的 wrapper Observable 物件呼叫 subscribe,這時候就會觸發包含業務邏輯的 Observable 物件的建立了:
defer 返回的 wrapper Observable 的訂閱函式在此處執行:
呼叫工廠方法,進行包含業務邏輯的 Observable 物件建立:
當前隨機數執行結果大於 0.5,返回 fromEvent 生成的新 Observable 物件。
緊接著,第24行的匿名函式 x => console.log(x),每當螢幕被滑鼠點選時,就會觸發。這個匿名函式本來是訂閱到 defer 函式返回的 wrapper Observable 物件的。當工廠函式返回了新的 Observable 物件後,它被自動訂閱到這個新的 Observable 物件上。
總結 defer 的工作原理:
(1) defer 函式被呼叫時,傳入一個工廠函式作為輸入引數。這個工廠函式返回一個新的包含了業務邏輯的 Observable 物件。
(2) defer 函式返回另一個新的 Observable 物件,這個 Observable 物件稱為 wrapper 或者 dummy Observable 物件,因為它不包含任何業務邏輯,存活的唯一價值就是,實現業務邏輯 Observable 物件的延遲建立。
(3) 當 wrapper Observable 被訂閱時,觸發工廠函式的執行,生成新的 Observable 物件,同時通知其 Observer.
更多Jerry的原創文章,盡在:"汪子熙":