我正在各种平台上尝试响应式扩展,而让我有点恼火的一件事是故障。
即使对于 UI 代码,这些故障可能不是那么成问题,并且通常可以找到解决它们的操作符,但我仍然发现在存在故障的情况下调试代码更加困难:中间结果对于调试并不重要,但我的想法不知道结果何时是中间或“最终”。
在 Haskell 和同步数据流系统中使用纯功能 FRP 进行了一些工作后,它也“感觉”错了,但这当然是主观的。
但是当将 RX 连接到非 UI 执行器(如电机或开关)时,我认为故障问题更大。如何确保只有正确的值被发送到外部执行器?
也许这可以通过一些知道一些“外部传感器”何时触发启动事件的“调度程序”来解决,以便在将最终结果转发给执行器之前处理所有内部事件。类似于flajax论文中描述的东西。
我希望得到答案的问题是:
- RX 中是否存在无法修复同步通知故障的问题?
- 如果没有,RX 是否存在(最好是生产质量)库或方法来修复同步故障?特别是对于单线程 Javascript,这可能有意义吗?
- 如果不存在通用解决方案,如何使用 RX 来控制外部传感器/执行器而不会在执行器上出现故障?
让我举个例子
假设我想打印(a,b)
合同所在的元组序列
a=n b=10 * floor(n/10)
n 是自然数流 = 0,1,2....
所以我期望以下序列
(a=0, b=0)
(a=1, b=0)
(a=2, b=0)
...
(a=9, b=0)
(a=10, b=10)
(a=11, b=10)
...
在 RX 中,为了让事情更有趣,我将使用过滤器来计算 b 流
var n = Observable
.Interval(TimeSpan.FromSeconds(1))
.Publish()
.RefCount();
var a = n.Select(t => "a=" + t);
var b = n.Where(t => t % 10 == 0)
.Select(t => "b=" + t);
var ab = a.CombineLatest(b, Tuple.Create);
ab.Subscribe(Console.WriteLine);
这给出了我认为是一个小故障(暂时违反不变量/合同):
(a=0, b=0)
(a=1, b=0)
(a=2, b=0)
...
(a=10, b=0) <-- glitch?
(a=10, b=10)
(a=11, b=10)
我意识到这是 CombineLatest 的正确行为,但我也认为这被称为故障,因为在真正的纯 FRP 系统中,您不会得到这些违反中间不变性的结果。
请注意,在此示例中,我将无法使用 Zip,而且 WithLatestFrom 也会给出不正确的结果。
当然,我可以将这个例子简化为一个单子计算,从不多播 n 个流事件(这意味着不能过滤而只能映射),但这不是重点:在 RX 中的 IMO 你总是得到一个“故障” ' 每当您拆分并重新加入可观察流时:
s
/ \
a b
\ /
t
例如,在 FlapJAX 中,您不会遇到这些问题。
这有什么意义吗?
非常感谢,彼得