【发布时间】:2014-12-22 04:43:47
【问题描述】:
作为一项练习,我正在尝试构建 2 个相互更新的依赖流。
测试应用程序只是一个“英寸 厘米”转换器,两个输入均可编辑。
我遇到的问题是我无法理解如何停止导致一个字段更改的递归。
为了更好地解释这个问题,让我们看一下代码的相关部分:
var cmValue = new Rx.BehaviorSubject(0),
inValue = new Rx.BehaviorSubject(0);
# handler #1
cmValue.distinctUntilChanged().subscribe(function(v) {
inValue.onNext(cmToIn(v));
});
# handler #2
inValue.distinctUntilChanged().subscribe(function (v) {
cmValue.onNext(inToCm(v));
});
所以我们给 Subjects 定义了每一个都持有当前对应的值。
现在假设我们以英寸为单位将值更改为 2(使用 inValue.onNext(2); 或通过键盘)。
接下来会发生什么 - 处理程序 #2 被触发并调用相应的重新计算以厘米为单位的值。结果到cmValue.onNext(0.7874015748031495)。
这个调用实际上由处理程序 #1 处理,并使用 0.7874015748031495 * 2.54 公式重新计算以英寸为单位的值(我们手动输入的值),这会导致另一个 inValue.onNext(1.99999999999999973) 调用。
幸运的是 - 由于 FP 舍入错误,我们停止了。但在其他情况下,这可能会导致更多循环甚至无限递归。
如您所见 - 我部分解决了应用 .distinctUntilChanged() 的问题,这至少可以保护我们免受任何更改的无限递归,但正如我们所见 - 在这种情况下,它并不能完全解决问题,因为值不是相同(由于 FP 操作性质)。
所以问题是:如何实现一个完全不会导致自递归的通用双向绑定?
我强调通用是为了说明使用带有舍入的.select() 将是这个特定问题的部分解决方案,而不是通用的(我和其他所有人都更喜欢)。
完整代码及演示:http://jsfiddle.net/ewr67eLr/
【问题讨论】:
-
从问题中不清楚为什么需要递归。您可以让来自输入 A 的事件更新 B,来自输入 B 的事件更新 A 而无需流相互引用。 IE。分配给 cmElement.value 不会生成事件,因此没有循环。例如jsfiddle.net/kcv15h6p/1 你在这里创建了一个循环,通过引入不需要解决所述问题的连接主题。但是,您可以在需要时在 Rx 中安全地创建循环。也许用需要循环的问题来更新问题。
-
@user1009908:我不需要需要递归。我的问题是如何消除它。 “也许用需要循环的问题来更新问题”---问题已经描述过了,抱歉。我喜欢你的解决方案。热衷于将其作为答案?
标签: javascript reactive-programming rxjs reactive-extensions-js