簡體   English   中英

使用reactiveui + throttle調用異步方法的最佳方法是什么

[英]What is the best way to call async methods using reactiveui + throttle

我正在嘗試使用Rx + ReactiveUI來解決我的第一個任務,並且正在尋找解決任務的最佳實踐,顯示一個輸入框,一旦用戶開始輸入就會顯示建議。

根據以下代碼示例,異步加載建議的最佳方法是什么? 使用Subscribe還是使用Select Many 或者有更好的方法來實現這兩個目標嗎?

     this.SearchTerms = this.ObservableForProperty(x => x.SearchTerm)
            .Throttle(SuggestionThrottle, RxApp.MainThreadScheduler)
            .Value()
            .SelectMany(async s => await this.LoadSearchSuggestions(s));  // 1st Possibility

        this.SearchTerms.Subscribe(this.LoadSearchSuggestions);           // 2nd Possibility

您必須以任何方式致電Subscribe

Rx中的查詢使用延遲評估,這意味着僅定義查詢不會啟動它。 延遲評估允許您通過有條件地應用運算符來構建查詢,僅將查詢定義一次並將其存儲在字段中以供日后使用,或者在調用Subscribe之前傳遞引用而不會產生任何副作用。

如果不調用Subscribe您的查詢將保持不活

Subscribe通過將您的IObserver<T>傳遞給observable來激活查詢,或者您可以使用其重載,允許您單獨提供OnNextOnError和/或OnCompleted處理程序,Rx將為您轉換為IObserver<T> IObserver<T>接收查詢的通知。

Subscribe的無參數重載在內部使用靜默觀察器,目的是僅為其副作用啟動查詢。 例如,在您的情況下,如果您使用SelectMany完成加載建議的所有工作而您不需要單獨的IObserver<T> ,那么您將通過調用Subscribe的無參數重載來啟動查詢。

在大多數情況下,您不應使用Subscribe的無參數重載。 Subscribe點是您傳遞給它的IObserver<T> (或單個處理程序)旨在導致查詢的副作用。 通過僅在Subscribe或例如Do運算符中引起副作用,查詢更容易推理和維護。

但是,有一個相當常見的情況,使用Subscribe的無參數重載是有意義的:如果查詢的副作用是由異步方法引起的,那么使用SelectMany以及Subscribe的無參數重載是最好的。

原因很簡單: SelectMany是順序組合運算符,它使您可以將異步方法作為查詢中的順序步驟調用。 因此, SelectMany將訂閱的取消與取消異步計算聯系起來。 訂閱(由所表示的處置IDisposble是從調用返回Subscribe )導致CancellationToken由特殊異步重載提供SelectMany操作員用信號注銷。 您的異步方法可以監視CancellationToken以提前退出其計算。

Subscribe中沒有任何重載接受異步觀察者,因此OnNext返回一個Task 但即使您在OnNext處理程序中調用返回void的異步方法,也不會在處理訂閱時發出異步方法的信號。

請注意,無論如何,您的兩個代碼示例都略有錯誤。 第一個示例不需要asyncawait關鍵字。 如上所述, SelectMany有一些特殊的重載接受一個Task<T>返回選擇器函數,以及為該函數提供CancellationToken額外重載。 你可能應該使用后者。

你的第二個例子不應該編譯,假設LoadSearchSuggestions返回Task (除非ReactiveUI庫或您引用的其他庫提供了一個Subscribe的重載,它接受一個Task -returning函數,在這種情況下,您將不得不查閱他們的文檔。)

除非后者,並假設您的其余查詢是正確的,這是您應該做的:

this.SearchTerms = this.ObservableForProperty(x => x.SearchTerm)
  .Throttle(SuggestionThrottle, RxApp.MainThreadScheduler)
  .Value()
  .SelectMany(LoadSearchSuggestionsAsync)
  .Subscribe();

其中LoadSearchSuggestionsAsync的定義如下:

async Task<Unit> LoadSearchSuggestionsAsync(string term, CancellationToken cancel)
{
  ...
  return Unit.Default;
}

請注意, Unit表示Rx中的void 這是必需的,因為返回非泛型Task的異步方法不能與SelectMany一起使用。 如果您要返回實際數據,則只需將Unit替換為您的數據類型即可。 然后,您還可以將OnNext處理程序傳遞給Subscribe ,並使用返回值執行某些操作,例如日志記錄。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM