【问题标题】:Reactive Extensions Switch() in search搜索中的反应式扩展 Switch()
【发布时间】:2013-11-03 12:01:07
【问题描述】:

经典实时搜索示例:

var searchResults = from input in textBoxChanged
                    from results in GetDataAsync(input)
                    select results;

GetDataAsync 返回一个:

 Task<List<DataRecord>>

这显然是一个竞争条件,所以如果由第二个输入触发的搜索在第一个输入之前返回,则第一个输入的结果在后面,因此给我错误的数据。

我一直在读到 .Switch() 运算符会神奇地解决这个问题,但是如何解决呢?

.Switch() 仅存在于:

 IObservable<IObservable<T>>

【问题讨论】:

    标签: system.reactive reactive-programming


    【解决方案1】:

    假设

    我会假设 textBoxChanged 是由类似的东西创建的:

    var textBoxChanged = Observable.FromEventPattern(x, "TextChanged")
                                   .Select(evt => ((TextBox)evt.Sender).Text);
    

    使用 SelectMany 时防止竞争条件

    from... from... 在 LINQ 理解中转换为 SelectMany,这就是您正在使用的。 Rx 足够聪明,可以将GetDataAsync(input) 返回的Task&lt;List&lt;DataRecord&gt;&gt; 转换为IObservable&lt;List&lt;DataRecord&gt;&gt;

    问题是您想阻止结果来自除最近提交的搜索请求之外的所有搜索请求。

    为此,您可以利用TakeUntil。它具有以下签名:

    public static IObservable<TSource> TakeUntil<TSource, TOther>(
        this IObservable<TSource> source,
        IObservable<TOther> other
    )
    

    它从源 observable 序列返回值,直到另一个 observable 序列产生值。

    我们可以这样使用它:

    var searchResults = from input in textBoxChanged
                        from results in GetDataAsync(input).ToObservable().TakeUntil(textBoxChanged)
                        select results;
    

    这将阻止竞争条件,但也会订阅两次 textBoxChanged。

    改用Switch

    这是一种非常有用的模式,因此使用Switch() 运算符引入了另一种方法,该运算符也负责双重订阅。

    不使用SelectMany,只需将输入直接投影到搜索查询中——这将给出IObservable&lt;IObservable&lt;List&lt;DataRecord&gt;&gt;的返回类型,一个流的流。 Switch 会从一个流跳到另一个流,只返回最新的流。这相当于 SelectMany/TakeUntil 组合:

    var searchResults = (from input in textBoxChanged
                         select GetSearchResults(input).ToObservable())
                        .Switch();
    

    I highly suggest looking at the Rx Hands on Lab that explains this in much more detail.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-17
      • 1970-01-01
      • 1970-01-01
      • 2011-02-10
      • 2011-08-27
      • 2012-01-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多