System.reactive 搜索中的被动扩展开关()
经典的实时搜索示例:System.reactive 搜索中的被动扩展开关(),system.reactive,reactive-programming,System.reactive,Reactive Programming,经典的实时搜索示例: var searchResults = from input in textBoxChanged from results in GetDataAsync(input) select results; GetDataAsync返回一个: Task<List<DataRecord>> 任务 这显然是一个竞争条件,因此如果由第二个输入触发的搜索在第一个输入之前返回,则
var searchResults = from input in textBoxChanged
from results in GetDataAsync(input)
select results;
GetDataAsync返回一个:
Task<List<DataRecord>>
任务
这显然是一个竞争条件,因此如果由第二个输入触发的搜索在第一个输入之前返回,则第一个输入的结果在第一个输入之后,因此给我错误的数据
我到处都在读到.Switch()操作符会神奇地解决这个问题,但是如何解决呢
.Switch()仅存在于:
IObservable<IObservable<T>>
IObservable
假设
我假设textBoxChanged是由以下内容创建的:
var textBoxChanged = Observable.FromEventPattern(x, "TextChanged")
.Select(evt => ((TextBox)evt.Sender).Text);
使用SelectMany时防止竞争情况
从。。。从…起在LINQ中,理解转换为SelectMany
,这就是您正在使用的。Rx足够智能,可以将GetDataAsync(input)
返回的任务
转换为IObservable
问题在于,您希望阻止从除最近提交的搜索请求之外的所有搜索请求返回结果
要做到这一点,您可以利用。其签名如下:
public static IObservable<TSource> TakeUntil<TSource, TOther>(
this IObservable<TSource> source,
IObservable<TOther> other
)
这将阻止竞争条件,但也将订阅两次textBoxChanged
改用开关
这是一种非常有用的模式,使用Switch()
操作符引入了一种替代方法,该操作符还负责双重订阅
不要使用SelectMany
,只需将输入直接投射到搜索查询中,这将给出一个返回类型IObservable
var searchResults = from input in textBoxChanged
from results in GetDataAsync(input).ToObservable().TakeUntil(textBoxChanged)
select results;
var searchResults = (from input in textBoxChanged
select GetSearchResults(input).ToObservable())
.Switch();