javascript - Bacon.js 中的 mergeWith 与 onValues

标签 javascript jquery functional-programming reactive-programming bacon.js

我有 2 个 Bacon.jQuery Models(但问题可以用任何 Bacon Observable 来说明)。

我有 3 个组合框:foobarquuxbar 依赖于 fooquux 依赖于 barquux 的组合。有一个 findQuux 函数,它从 foobar 中查找 quux 组合框的值。

如果用户更改 foo 组合框,则选择 barquux 框中的值。以下是 quux 选择的有效实现:

// WORKS
var quuxBus = new Bacon.Bus()
Bacon.onValues(fooModel, barModel, function (foo, bar)
{
    quuxBus.push(findQuux(foo, bar))
})
quuxModel.addSource(quuxBus.toProperty('quux4'))

此解决方案有一个小问题,因为我需要 'quux4' hack 才能在页面加载时正确设置 quux。但以下更简单的解决方案根本不起作用:

// DOESN'T WORK
var quuxCombo = Bacon.combineWith(findQuux, fooModel, barModel)
quuxModel.addSource(quuxCombo)

问题是 findQuux 需要 foobar 的有效组合,并且当输入不可能的组合时会崩溃,而 >quux 找不到。

onValues/push 解决方案之所以有效,是因为当用户更改 foo 组合框时,findQuux 仅被调用一次。 bacon.combineWith 解决方案不起作用,因为 findQuux 被调用了两次。

实现quuxModel数据源的推荐方法是什么?防御性地编码 findQuux 不是一个选择。

完整代码可以在 http://jsfiddle.net/5zp4D/8/ 找到

更新:页面加载时 foobar 已经有了合理的值。从 fiddle 链接可以看出,fooModel 使用显式值进行初始化,并且 barModel 是根据该初始值重新计算的:

var fooModel = Bacon.$.selectValue(fooDom, 'foo2-value')
var barModel = Bacon.$.selectValue(barDom)

barModel.addSource(fooModel.map(function (x)
{
    return json[x][1].val
}))

foobar 永远不会采用无效值。此外,一旦用户更改 foobar 就会重新填充,因此 UI 中只能看到有效的组合。

combineWith 方法的问题在于,当用户切换 foo 时,findQuux 函数会使用中间值调用两次,其中一个中间组合是不正确的,而组合成分单独是正确的。我改变了 fiddle 以更好地说明问题:http://jsfiddle.net/5zp4D/12/

var json 可以看出,有效组合是 1-1、1-2、2-3、2-4 和 2-5。

我取消了损坏版本的注释,添加了日志记录。当您选择 foo1 ,然后在第一个组合框中选择返回 foo2 时,您会在日志中收到 4 条消息,而不是 3 条:

在页面加载时,您会看到 quux 值已正确初始化 (2-4):

"valid combination of foo2-value and bar4-value"

当您选择 foo1 而不是 foo2 时,您会看到 findQuuxDef 被调用为 1-4 (foo是新的,bar 是旧的),然后是 2-4(foo 是新的,bar 是新的):

"invalid combination of foo1-value and bar4-value"
"valid combination of foo1-value and bar2-value"

我的问题是,使用 onValues/push 方法不会发生无效的中间组合,我想知道使用链接元素的 UI 的惯用推荐方法是什么。

最佳答案

我首先让 quuxCombo 仅输出 findQuux 的有效值。我更喜欢在页面加载时为输入 foobar 提供合理的值,但如果这是不可能的(为什么不呢?),我会使用 filter 在输入上。例如,

var quuxCombo = Bacon.combineWith(findQuux, fooModel.filter(validFoo), barModel.filter(validBar))

不过,我想您希望在有效输入存在之前从一些初始值开始。为此,我在 Bacon.js 0.6.15 中添加了一个新方法 Property.startWith。所以,现在你可以

var quuxCombo = Bacon.combineWith(findQuux, fooModel.filter(validFoo), barModel.filter(validBar)).startWith("quux4")

关于javascript - Bacon.js 中的 mergeWith 与 onValues,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18701280/

相关文章:

javascript - 如何在 vue.js 对象内循环数组

javascript - 使用 html 和 Javascript 进行客户端排序

javascript - 如何检查是否使用 jQuery 检查了 div 中的所有复选框?

functional-programming - 定义引用透明度和确定性函数之间有什么区别?

haskell - 确定总的终止函数

javascript - 提高此方法的性能以展平数组

javascript - 从 AJAX 调用 WordPress PHP 函数

javascript - jQuery .html() 匿名函数返回oldHtml

javascript - 如何在表中该行的其他可用下拉列表中的下拉列表中显示取消选择的选项 - jquery

Haskell 重构建议