为什么 IObservables 链完全为每个订阅解析?

Why are chains of IObservables resolved entirely for each subscription?

我对如何解析 IObervables 链有疑问。 我认为,如果多个观察者订阅同一个 IObservable,那么如果流发出一个新项目,整个链将只被解析一次。

相反,对于每个订阅,整个链似乎是 运行。

如果我的整个程序逻辑是使用 IObservables 并将它们链接在一起的,那么在我看来,代码是 运行unnesslessly 具有相同结果的相同方法。

以下代码是用 LINQPad 编写的:

{
    var subject = Observable.Range(1, 1);

    var observable1 = subject
        .Select(value =>
        {
            var nextValue = value + 2;
            Console.Write("\n Result of expensive computation: " + nextValue);
            return nextValue;
        });

    var observable2 = observable1
        .Select(value =>
        {
            var nextValue = 2 * value;
            Console.Write("\n Result of another expensive computation: " + nextValue);
            return nextValue;
        });

    observable2.Subscribe(_ => Console.Write("\n Data received on first subscription."));

    observable2.Subscribe(_ => Console.Write("\n Data received on second subscription."));
}

结果:

Result of expensive computation: 3

Result of another expensive computation: 6

Data received on first subscription.

Result of expensive computation: 3

Result of another expensive computation: 6

Data received on second subscription.

然而我期望:

Result of expensive computation: 3

Result of another expensive computation: 6

Data received on first subscription.

Data received on second subscription.

感谢您的回答。

干杯, 罗布

第一个回答你的问题:

  • 是的,这是预期的行为。
  • 是的,可以避免。
  • 回避是个不错的主意。

正如@supertopi 所说,您创建了一个冷可观察对象,其功能与您概述的一样。将它变成热可观察对象,您将拥有所需的功能。

您可以按如下方式操作:

{
    var subject = Observable.Range(1, 1);

    var observable1 = subject
        .Select(value =>
        {
            var nextValue = value + 2;
            Console.Write("\n Result of expensive computation: " + nextValue);
            return nextValue;
        });

    var observable2 = observable1
        .Select(value =>
        {
            var nextValue = 2 * value;
            Console.Write("\n Result of another expensive computation: " + nextValue);
            return nextValue;
        });

    var hotObservable = observable2.Publish().RefCount();

    hotObservable.Subscribe(_ => Console.Write("\n Data received on first subscription."));

    hotObservable.Subscribe(_ => Console.Write("\n Data received on second subscription."));

}

冷 Observables:

  • 多次订阅触发链式操作多次代码重运行
  • 通常来自 Observable.Create/Range/Generate/Interval/Timer
  • 就像一个可枚举的项目,在项目之间明确定义了时间间隔。

热门 Observables:

  • 多个订阅一般共享链式操作的结果
  • 通常来自事件、已发布的冷观测值或 Subject
  • 喜欢你可以处理的一系列事件;不管你喜不喜欢,它们都会发生。

在我看来,最好的区别在于来源是否 'running' 没有订阅。例如,无论是否有人订阅,按钮点击事件仍然会发生。相反,Observable.Timer 在没有订阅的情况下什么都不做。

至于为什么...我不能代表 Rx 设计师。冷与热 observables 是 confusion/bugs 的常见来源。我认为围绕它们有更好的明确性可以改善这种情况。话虽如此,我不确定那是或现在是如何做到的。