在反应式编程中推送值时的指数时间和不一致的瞬态值?

exponential time and inconsistent transient values when pushing a value in reactive programming?

我是反应式编程的新手,我开始玩 kefirjs。 从表面上看,bacon/kefir 的事件流和属性本质上是一种表达 dependency/computation dag 的方式 随着时间的推移而变化,并且有巧妙的方法可以将这些 dags 连接到 DOM 事件和 UI。好的,听起来不错。

我知道一般来说,当你有一个计算 dag 时,如果你更改单个上游节点的值并天真地递归地将计算推到下游,众所周知的问题是:

  1. 相对于dag的个数,最多占用指数时间 受影响的节点

  2. 中间计算混合使用 输入节点的先前和当前值, 导致 strange/inconsistent 瞬态输出值。

我通过玩一些简单的玩具程序发现 kefir 天真地进行了此类更新,因此 (1.) 和 (2.) 确实发生了。 (我没吃过培根。)

这些还不算问题吗?

例如,在下面的程序中,我希望输出 x6 直接从 64 变为 640, 以 12 次组合器评估为代价(最初 6 次,6 次由单次更新触发)。 相反,输出变为 64,73,82,91,...,622,631,640(63 个无意义的中间值) 以 132 次组合器评估为代价(最初 6 次,这是有道理的,然后 126 次用于更新,这是过多的)。

https://codepen.io/donhatch/pen/EXYqBM/?editors=0010

// Basic plus
//let plus = (a,b)=>a+b;

// More chatty plus
let count = 0;
let plus = (a,b)=>{console.log(a+"+"+b+"="+(a+b)+"  count="+(++count)); return a+b;};

let x0 = Kefir.sequentially(100, [1,10]).toProperty();
let x1 = Kefir.combine([x0,x0], plus).toProperty();
let x2 = Kefir.combine([x1,x1], plus).toProperty();
let x3 = Kefir.combine([x2,x2], plus).toProperty();
let x4 = Kefir.combine([x3,x3], plus).toProperty();
let x5 = Kefir.combine([x4,x4], plus).toProperty();
let x6 = Kefir.combine([x5,x5], plus).toProperty();
x6.log('                x6');

我很困惑,开菲尔显然没有尝试有效地进行此类更新; 我认为这会使它成为真正应用程序的非启动器。

也许我误解了响应式编程的用途。 现实生活中的响应式应用程序中遇到的 dag 总是树,还是什么?

Bacon.js 有原子更新 (https://github.com/baconjs/bacon.js/#atomic-updates) 而开菲尔没有。这就是为什么使用 Bacon.js 你会看到你想要的行为,而使用开菲尔你会得到很多中间值。