[翻譯] 除錯 Rxjs(一):工具

Ice Panpan發表於2018-12-17

原文:Debugging RxJS, Part 1: Tooling

譯者:Ice Panpan;校驗者:暫無

[翻譯] 除錯 Rxjs(一):工具

我是一個 Rxjs 的信仰者,我在我所有的專案中都使用 Rxjs。有了 Rxjs,我發現很多曾經覺得乏味的事都變得痛快。但是有一件事不是這樣:除錯。

Rxjs 中非同步的本質在組合之後讓除錯變得更具挑戰性:沒有太多的狀態(state)供你檢查,並且呼叫堆疊(call stack)也幫不了太大的忙。我過去使用的方法是在整個程式碼多處新增 do 操作符並且記錄,以此來檢查那些組合的 Observable 產生的值。這並不是我想要的方法,因為:

  1. 當我在除錯時修改程式碼,我不得不進行更多的日誌記錄工作;
  2. 當除錯結束之後,我必須刪除日誌記錄或者註釋掉它;
  3. 當在一個正常的組合Observable中存在‘拍扁’的操作時,如何進行日誌記錄需要格外的小心。
  4. 就算是專門有的 log 操作符,結果也不會很理想。

最近,我留了一些時間來為 Rxjs 構建一個除錯工具,我覺得這個工具必須具備以下的功能:

  1. 應該儘可能的不顯眼;
  2. 不需要通過修改程式碼來進行除錯;
  3. 在除錯結束後,不需要刪除或註釋掉除錯的程式碼;
  4. 應該可以輕鬆的啟用和禁用日誌記錄;
  5. 它應該提供與瀏覽器控制檯的一些整合————用於開啟/關閉除錯用能和檢查狀態等。

如果想要更完美,還要一些東西:

  1. 它應該支援暫停 Observable
  2. 它應該支援修改 Observable 或者它們發出的值;
  3. 它應該支援控制檯意外的日誌記錄機制;
  4. 它應該是可擴充套件的;
  5. 它應該在某種程度上可以捕獲視覺化訂閱依賴關係所需的資料。

考慮到這些功能,我建立了 rxjs-spy

核心概念

rxjs-spy 引入了 tag 操作符,將字串標記與 Observable 相關聯。這個操作符不會以任何方式更改 Observable 的行為或值。

tag 操作符可以被單獨匯入-js import "rxjs-spy/add/operator/tag"-並且其他的 rxjs-spy 方法可以在生產環境下省略,所以唯一的開銷就是字串註釋。

大多數工具的方法接受匹配器,以確定它們將應用於哪些標記的 Observable 。匹配器可以是傳遞標籤本身的簡單字串,正規表示式或謂詞。

通過呼叫 spy 來配置工具時,它會修改 Observable.prototype.subscribe 來監聽所有的 subscriptions, notificationsunsubscriptions。這也就是意味著,只有已經被訂閱的 Observable 才會被監聽。

rxjs-spy 公開了一個旨在從程式碼中呼叫的模組API和一個用於在瀏覽器控制檯中互動使用的控制檯API。大多數時候,我早早地在應用程式啟動程式碼裡條用模組API的方法,並使用控制檯API進行剩餘的除錯。

控制檯API功能

在除錯時,我通常使用瀏覽器的控制檯來檢查和操作標記的 Observables。控制檯API功能最容易通過示例解釋:

import { Observable } from "rxjs/Observable";
import { spy } from "rxjs-spy";

import "rxjs/add/observable/interval";
import "rxjs/add/operator/map";
import "rxjs/add/operator/mapTo";
import "rxjs-spy/add/operator/tag";

spy();

const interval = new Observable
  .interval(2000)
  .tag("interval");

const people = interval
  .map((value) => {
    const names = ["alice", "bob"];
    return names[value % names.length];
  })
  .tag("people")
  .subscribe();
複製程式碼

rxjs-spy 中的控制檯API通過 rxSpy 在全域性暴露。

呼叫 rxSpy.show() 將顯示所有已經被標記的 Observable 的列表,指示其狀態(incompletecomplete 或者 errored),訂閱者(subscribers)的數量和最近發出的值(如果已經發出一個值)。控制檯輸出將如下所示:

[翻譯] 除錯 Rxjs(一):工具

要顯示特定標記的 Observable 的資訊,可以將標記名稱或者正規表示式傳遞給 show

[翻譯] 除錯 Rxjs(一):工具

可以通過呼叫 rxSpy.log 來顯示被標記的 Observable 的日誌資訊:

[翻譯] 除錯 Rxjs(一):工具

log 不帶引數呼叫將會顯示所有標記的 Observable 的日誌記錄。

模組API中的大多數方法都返回一個撤銷功能,可以呼叫該功能來撤銷方法呼叫。在控制檯中,管理起來很繁瑣,所以還有另一種選擇。

呼叫 rxSpy.undo() 將顯示已經呼叫的方法的列表:

[翻譯] 除錯 Rxjs(一):工具

呼叫 rxSpy.undo 並傳遞與方法呼叫關聯的數字將看到該呼叫的撤銷函式被執行。例如,呼叫 rxSpy.undo(3) 將看到被標記為 intervalObservable 的記錄被撤銷之後的結果:

[翻譯] 除錯 Rxjs(一):工具

有時,在除錯時修改 Observable 或其值時,這個方法就很有用。控制檯API包含一種 let 方法,其功能與 RxJS 中的 let 操作符大致相同。它的實現方式是通過呼叫 let 方法對標記的 Observable 的當前和未來的訂閱者產生影響。例如。以下呼叫將看到 people Observable 發射 mallory 而不是 alicebob:

[翻譯] 除錯 Rxjs(一):工具

log 方法一樣,let 可以撤消對該方法的呼叫:

[翻譯] 除錯 Rxjs(一):工具

能夠在除錯時暫停一個 Observable 對我來說幾乎是不可或缺的。呼叫 rxSpy.pause 將暫停一個標記的 Observable,並返回一個可用於控制和檢查 Observable 的通知(notifications)的 deck

[翻譯] 除錯 Rxjs(一):工具

在該 deck 上呼叫 log 將顯示 Observable 是否暫停,並顯示被暫停的通知(notifications)。(通知是 Notification 使用 materialize 操作符獲得的rxjs例項)

[翻譯] 除錯 Rxjs(一):工具

deck 上呼叫 step 將發出一個被暫停住的通知(notifications):

[翻譯] 除錯 Rxjs(一):工具

呼叫 resume 將發出所有被暫停的通知(notifications),並將恢復 Observable

[翻譯] 除錯 Rxjs(一):工具

呼叫 pause 將看到 Observable 重新進入暫停狀態:

[翻譯] 除錯 Rxjs(一):工具

很容易忘記將返回的 deck 分配給變數,因此控制檯API包含一個 deck 方法,和 undo 方法行為相似。呼叫它將顯示 pause 呼叫的列表:

[翻譯] 除錯 Rxjs(一):工具

呼叫它並傳遞與呼叫相關聯的數字將返回相對應的 deck

[翻譯] 除錯 Rxjs(一):工具

loglet 的呼叫一樣,pause 的呼叫也可以撤銷。撤銷 pause 的呼叫將看到標記的 Observable 恢復正常:

[翻譯] 除錯 Rxjs(一):工具

希望以上的例子可以對 rxjs-spy 的控制檯API進行一個概述。Debugging RxJS 的後續部分將重點介紹 rxjs-spy 的具體功能以及如何使用它們來解決實際的除錯問題。

對我來說,rxjs-spy 肯定讓除錯Rxjs不再那麼繁瑣。

更多資訊

rxjs-spy 的程式碼可以在 GitHub上找到,並且有一個線上的控制檯API示例

該包可以通過NPM進行安裝。

有關本系列的一下篇文章,請參閱除錯 Rxjs(二):日誌記錄

相關文章