为什么 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 的常见来源。我认为围绕它们有更好的明确性可以改善这种情况。话虽如此,我不确定那是或现在是如何做到的。
我对如何解析 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 的常见来源。我认为围绕它们有更好的明确性可以改善这种情况。话虽如此,我不确定那是或现在是如何做到的。