代码之家  ›  专栏  ›  技术社区  ›  stakx - no longer contributing Saravana Kumar

Rx:可观察的对象是否像IEnumerable一样是“可重复的”,如果不是,这个代码是如何工作的?

  •  2
  • stakx - no longer contributing Saravana Kumar  · 技术社区  · 14 年前

    昨天我看了电影 Writing your first Rx Application (第9频道)Wes Dyer展示了如何使用 Reactive Extensions (Rx)

    在屏幕播放的最后,Wes Dyer输入以下内容:

    var q = from start in mouseDown
            from delta in mouseMove.StartsWith(start).Until(mouseUp)
                           .Let(mm => mm.Zip(mm.Skip(1), (prev, cur) =>
                               new { X = cur.X - prev.X, Y = cur.Y - prev.Y }))
            select delta;
    

    q 是将鼠标移动坐标增量推送到订阅服务器的可观察对象。

    我不明白的是 mm.Zip(mm.Skip(1), ...) 可能有用!?

    据我所知, IObservable IEnumerable I可数 ,它可以反复迭代,总是产生相同的项。(至少是这个 应该 可观察的

    那么,如何结合 .Zip .Skip(1) 可能有用,因为他们正在处理的鼠标事件是单一的、不可重复的事件?这个手术不需要吗 mm “看”两次了吗?


    以下是签名的方法,以供参考 Observable.Zip :

    public static IObservable<TResult> Zip <TLeft, TRight, TResult>
    (
        this IObservable<TLeft>       leftSource,     //  = mm
        IObservable<TRight>           rightSource,    //  = mm.Skip(1)
        Func<TLeft, TRight, TResult>  selector
    )
    

    我刚看到还有一个 screencast on the Zip operator

    3 回复  |  直到 14 年前
        1
  •  3
  •   Nappy    14 年前

    这个操作不要求mm被单独“看”两次吗?

    事实上,这就是你问题的答案:你可以订阅相同的 IObservable 多次排序。

    这个 mm.Skip(1) 订阅 mm 并将第一个值隐藏给它自己的订户。 Zip是两者的订户 嗯。跳过(1) . 因为 毫米 产生的价值比 嗯。跳过(1) ,Zip在内部缓冲来自的最后一个mousemove事件 所有的时间,以压缩它与下一个未来mousemove事件。选择器功能可以选择两者之间的增量。

    你应该注意的另一件事是(这是你问题标题的真实答案),这个 Observable.FromEvent - 可观察的 热的 可见因此 . 但确实有 寒冷的 事实上是 可重复的 ,就像可观测范围(0,10). 在后一种情况下,每个订户将接收相同的10个事件,因为它们是为每个订户独立生成的。对于mousemove事件,情况并非如此(您不会得到过去的mouse move事件)。但是因为Zip同时订阅了左右序列,所以在本例中可能是相同的。

    附言:你也可以用板条箱装热的/不可重复的 IEnumerable :它不需要为每个枚举数返回相同的值。例如,您可以创建一个IEnumerable,该IEnumerable等待mousemove事件发生,然后生成该事件。在这种情况下,枚举器总是阻塞(糟糕的设计),但这是可能的。;)

        2
  •  2
  •   stakx - no longer contributing Saravana Kumar    14 年前

    啊哈!这个 Zip screencast 拉链 “记住”项来解释这样一个事实,即从一个可观察到的项可能比从另一个可观察到的项来得早。我将试着回答我的问题,如果我错了,我希望有人能纠正我。

    拉链 将两个可观察序列的输入配对如下(字母和数字是“事件”):

    mm                        ----A---------B-------C------D-----------E----->
                                  |         |       |      |           |
                                  |         |       |      |           |
    mm.Skip(1)                ----+---------1-------2------3-----------4----->
                                  |         |       |      |           |
                                  |         |       |      |           |
    mm.Zip(mm.Skip(1), ...)   ----+--------A,1-----B,2----C,3---------D,4---->
    

    它确实需要做内部缓冲。在我发布的代码中, mm 是真实的,可以观察到的。 mm.Skip(1)

    所以, mm.Zip(mm.Skip(1), ...) 确实是看 毫米 Skip(n) 过滤器。因为可观察的是不可重复的序列,所以它做了内部缓冲来解释一个序列比另一个序列更快地产生项目的事实。

    拉链 涉及 Queue .)

        3
  •  1
  •   Alex Paven    14 年前

    项目被推送到订阅服务器一次,就是这样。