1

我对反应式编程相当陌生,我开始使用kefirjs。从表面上看, bacon /kefir 的事件流和属性本质上是一种表达随时间变化的依赖/计算 dag 的方式,并且有一些巧妙的方法可以将这些 dag 连接到 DOM 事件和 UI。好的听起来不错。

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

  1. 相对于受影响的 dag 节点的数量,它需要指数级的时间

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

我从玩一些简单的玩具程序中看到,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');

我很困惑,开菲尔显然没有尝试有效地进行此类更新。我认为这将使它成为真正的应用程序的初学者。

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

4

1 回答 1

2

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

于 2017-06-12T07:54:08.247 回答