与Bacon.js中的vsValues相结合

时间:2013-09-09 15:03:11

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

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

我有3个组合框:foobarquuxbar取决于fooquux取决于barquux的组合。有一个findQuux函数可以从quuxfoo找到bar组合框的值。

如果用户更改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'黑客在页面加载时正确设置quux。但是以下更简单的解决方案根本不起作用:

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

问题在于,findQuux需要foobar的有效组合,并且在使用无法找到quux的不可能组合时会崩溃。

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

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

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

找到

更新:页面加载中foobar已有合理的值。从小提琴链接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从不接受无效值。此外,一旦用户更改barfoo就会重新填充,因此在用户界面中只能看到有效的组合。

combineWith方法的问题是当用户切换foo时,findQuux函数被调用两次中间值,其中一个中间组合不正确,而组合成分是分开正确的。我改变了小提琴以更好地说明问题: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的惯用推荐方法。

1 个答案:

答案 0 :(得分:1)

我首先让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")