我如何组合三个可观察量,使得 [英] How do I combine three observables such that

查看:22
本文介绍了我如何组合三个可观察量,使得的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有三个 observable,我该如何组合它们,这样当第一个发出新值时,我可以将它与其他两个发出的最新值组合起来.重要的是我们只产生组合的新值observables 当第一个 observable 有新值时,不管其他两个是否发出了新值.

If I have three observables, how do I combine them such that when the first emit a new value, I can combine that with the latest emitted from the other two.. Its important that we only produce a new value of the combined observables when the first observable has a new value regardles of whether the other two has emitted new values.

谢谢.

推荐答案

您可以这样做(请注意,如果源 2 和 3 尚未发出,您将获得它们的默认值,并且我允许您有选择地提供这些默认值):

You could do this (note that you get default values for sources 2 and 3 if they have yet to emit, and I have allowed for you to optionally supply those default values):

public static class ObservableExtensions
{
    public static IObservable<TResult> CombineFirstWithLatestOfRest
        <TSource1, TSource2, TSource3, TResult>(
        this IObservable<TSource1> source1,
        IObservable<TSource2> source2,
        IObservable<TSource3> source3,
        Func<TSource1, TSource2, TSource3, TResult> resultSelector,
        TSource2 source2Default = default(TSource2),
        TSource3 source3Default = default(TSource3))
    {
        var latestOfRest = source2.CombineLatest(source3, Tuple.Create);
        return source1.Zip(latestOfRest.MostRecent(
            Tuple.Create(source2Default, source3Default)),
            (s1,s23) => resultSelector(s1, s23.Item1, s23.Item2));
    }
}

示例使用:

var source1 = Observable.Interval(TimeSpan.FromSeconds(2));
var source2 = Observable.Interval(TimeSpan.FromSeconds(1));
var source3 = Observable.Interval(TimeSpan.FromSeconds(3.5));

var res = source1.CombineFirstWithLatestOfRest(source2, source3,
    (x,y,z) => string.Format("1: {0} 2: {1} 3: {2}", x,y,z));    

res.Subscribe(Console.WriteLine);

附录

这里有一个微妙的问题,在您的场景中可能很重要.CombineLatest 有时不受欢迎的一个方面是它在每个贡献流都有一个值之前不会发出.这意味着在上面的示例中,较慢的 source3 会阻止 source2 并且会丢失值.具体来说,返回的事件将具有 source2source3 的默认值,直到 两者 各自发出至少一个事件.使用它们的默认值启动 source2source3 是这种行为的一种方便的解决方法,我们可以避免,因为它是驱动的 source1事件:

Addendum

There's a subtle problem here that might be significant in your scenario. A sometimes undesirable aspect of CombineLatest is that it does not emit until it has a value from every contributing stream. This means in the example above that the slower source3 holds up source2 and values are missed. Specifically, events returned will have the default values for both source2 and source3 until both have emitted at least one event each. Kicking off source2 and source3 with their default values is a convenient workaround for this behaviour, which we can get away with since it is source1 that drives events:

public static class ObservableExtensions
{
    public static IObservable<TResult> CombineFirstWithLatestOfRest
        <TSource1, TSource2, TSource3, TResult>(
        this IObservable<TSource1> source1,
        IObservable<TSource2> source2,
        IObservable<TSource3> source3,
        Func<TSource1, TSource2, TSource3, TResult> resultSelector,
        TSource2 source2Default = default(TSource2),
        TSource3 source3Default = default(TSource3))
    {   
        source2 = source2.StartWith(source2Default); // added this
        source3 = source3.StartWith(source3Default); // and this           
        var lastestOfRest = source2.CombineLatest(source3, Tuple.Create);            
        return source1.Zip(lastestOfRest.MostRecent(
            Tuple.Create(source2Default, source3Default)), // now redundant
            (s1,s23) => resultSelector(s1, s23.Item1, s23.Item2));
    }             
}

这篇关于我如何组合三个可观察量,使得的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆