术语:什么是函数式响应式编程/RX中的"glitch"?



在函数式响应式编程中,"故障"的定义是什么?

我知道在一些FRP框架中可能发生"故障",而在其他框架中则不会发生。例如,RX不是无故障的,而ReactFX是无故障的[1]。

是否有人能给出一个非常简单的例子来说明在使用RX时如何以及何时发生故障,并在同一个例子上显示相应的ReactFX解决方案如何以及为什么没有故障?

定义

我最喜欢的定义:

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

定义来自Scala。处方:

在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暂时与ab不一致

使用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);
});

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

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

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

和一个相关的SOF答案:如何避免Rx中的故障

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

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

A - B>

C ->

在这个简单的例子中,如果我更改了a,导致更改了B,但C还没有更新,就会发生故障。这是一个故障。

C与b不一致

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

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

下面是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

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

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

也许CombineLatest应该被称为WhenAnyReactiveUI库,这将澄清操作语义?

相关内容

  • 没有找到相关文章

最新更新