15

在函数响应式编程的上下文中,“故障”的定义是什么?

我知道在某些 FRP 框架中可能会出现“故障”,而在其他框架中则不会。例如,RX 不是无故障的,而 ReactFX 是无故障的 [ 1 ]。

有人可以举一个非常简单的例子来说明使用 RX 时故障是如何以及何时发生的,并在同一个例子中展示相应的 ReactFX 解决方案如何以及为什么没有故障。

谢谢阅读。

4

3 回答 3

20

定义

我(自己)最喜欢的定义:

故障是可观察状态中的暂时不一致。

来自Scala.Rx的定义:

在 FRP 的上下文中,故障是数据流图中的临时不一致。由于更新不会立即发生,而是需要时间来计算,因此 FRP 系统中的值可能会在更新过程中暂时不同步。此外,根据 FRP 系统的性质,可以在传播中多次更新节点。

例子

考虑整数变量a, b。定义sumprod,。
sum := a + b_
prod := a * b

让我们将此示例重写为 JavaFX:

IntegerProperty a = new SimpleIntegerProperty();
IntegerProperty b = new SimpleIntegerProperty();
NumberBinding sum = a.add(b);
NumberBinding prod = a.multiply(b);

现在让我们写一点一致性检查:

InvalidationListener consistencyCheck = obs -> {
    assert sum.intValue() == a.get() + b.get();
    assert prod.intValue() == a.get() * b.get();
};

sum.addListener(consistencyCheck);
prod.addListener(consistencyCheck);

a.set(1);
b.set(2);

此代码失败,最后一行出现断言错误,因为:

  • b已更新(至 2)
    • sum已更新(至 3)
      • 触发了`consistencyCheck`,`a == 1`,`b == 2`,但是`prod == 0`,因为`prod`还没有更新

这是一个小故障——prod暂时与aand不一致b

使用 ReactFX 消除故障

首先请注意,ReactFX并不是开箱即用的“无故障”,但它为您提供了消除故障的工具。除非您有意识地使用它们,否则 ReactFX 并不比 RX(例如 rxJava)更无故障。

在 ReactFX 中消除故障的技术依赖于事件传播是同步的这一事实。另一方面,RX 中的事件传播始终是异步的,因此这些技术无法在 RX 系统中实现。

在上面的示例中,我们希望将侦听器通知推迟到两者sumprod更新后。这是使用 ReactFX 实现此目的的方法:

import org.reactfx.Guardian;
import org.reactfx.inhibeans.binding.Binding;

IntegerProperty a = new SimpleIntegerProperty();
IntegerProperty b = new SimpleIntegerProperty();
Binding<Number> sum = Binding.wrap(a.add(b)); // Binding imported from ReactFX
Binding<Number> prod = Binding.wrap(a.multiply(b)); // Binding imported from ReactFX

InvalidationListener consistencyCheck = obs -> {
    assert sum.getValue().intValue() == a.get() + b.get();
    assert prod.getValue().intValue() == a.get() * b.get();
};

sum.addListener(consistencyCheck);
prod.addListener(consistencyCheck);

// defer sum and prod listeners until the end of the block
Guardian.combine(sum, prod).guardWhile(() -> {
    a.set(1);
    b.set(2);
});
于 2014-08-05T14:24:59.490 回答
4

简短回答:故障 = 不一致/非法/无意义的状态。

这是一个相关链接:https ://social.msdn.microsoft.com/Forums/en-US/bc2c4b71-c97b-428e-ad71-324055a3cd03/another-discussion-on-glitches-and-rx?forum=rx

另外,请参阅 Sodium 作者谈话的第 29 分钟以获得另一个答案:http: //youtu.be/gaG3tIb3Lbk

以及相关的 SOF 答案:如何避免 Rx 中的故障

因此,这是我根据 Tomas 的回答对故障的理解。

有一个数据流图,有 3 个节点:A、B、C

A->B

A->C

在这个简单的示例中,如果我更改 A 并导致更改 B 但 C 尚未更新,则会发生故障。这是一个故障。

C 与 B 不一致。

假设 B=2*A,C=2*A。

然后,如果 B 不等于 C,那么这是一个故障。

于 2015-01-27T13:49:44.310 回答
3

这是 C# RX 中致命“故障”情况的一个非常简短的理论示例

var t = Observable
        .Interval(TimeSpan.FromSeconds(1))
        .Publish()
        .RefCount();

var s = t.CombineLatest(t, (t1,t2) => 1/(1-(t1-t2));

由于t1t2都代表热观测值的最新值t,人们会假设t1-t2它总是如此0。所以 s 应该永远是1

但是当订阅 s 时,我们确实得到1了第一个观察值,但随后我们得到了除以零的异常。在 RxJS 中,我们会得到NaN.

原因很简单:当其中一个或产生一个值a.CombineLatest(b, f)时会做出反应,将这个新值与另一个可观察到的最后观察到的值结合起来。这是设计使然,但根据我的经验,使用 RX 的人有时会认为这些是故障,尤其是来自其他具有不同“最新”概念的 FRP 库时。ab

这当然是一个人为的例子,只是为了说明对CombineLatest.

也许CombineLatest应该WhenAny像在ReactiveUI库中那样调用,这会澄清操作语义?

于 2016-02-16T22:56:42.910 回答