[英]What is the best way to listen for complex object changes, using ReactiveUI?
[英]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來激活查詢,或者您可以使用其重載,允許您單獨提供OnNext
, OnError
和/或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的異步方法,也不會在處理訂閱時發出異步方法的信號。
請注意,無論如何,您的兩個代碼示例都略有錯誤。 第一個示例不需要async
和await
關鍵字。 如上所述, 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.