У меня есть 2 Bacon.jQuery Models
(но проблема может быть проиллюстрирована любым беконом Observable
).combWith vs onValues in Bacon.js
У меня есть 3 коробки со списком: foo
, bar
и quux
. bar
зависит от foo
и quux
зависит от комбинации: bar
и quux
. Существует функция findQuux
, которая находит значение для quux
combobox от foo
и bar
.
Если пользователь меняет foo
combobox, выбираются значения в bar
и quux
. Вот рабочая реализация 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
ожидает действительное сочетание foo
и bar
и аварий при скармливании невозможной комбинации, для которых quux
не может быть найден.
Решение onValues/push
работает, потому что findQuux
вызывается только один раз, когда пользователь меняет foo
combobox. Решение bacon.combineWith
не работает, потому что findQuux
вызывается дважды.
Каков рекомендуемый способ реализации источника данных для quuxModel
? Кодирование findQuux
- это не вариант.
Полный код можно найти на http://jsfiddle.net/5zp4D/8/
Update: Есть уже разумные значения для foo
и bar
от загрузки страницы. Как видно из скрипичной ссылки 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
}))
foo
и bar
никогда не принимают недопустимые значения. Кроме того, bar
заселяется после изменения пользователем foo
, поэтому в пользовательском интерфейсе видны только допустимые комбинации.
Проблема с 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
, и я хотел бы знать, что такое идиоматический рекомендованный подход к пользовательскому интерфейсу со связанными элементами.
Обновлен мой вопрос. 'fooModel.filter (validFoo)' не будет работать, потому что 'foo' и' bar' всегда действуют отдельно. Это их комбинация недействительна, поскольку поиск в паре не находит комбинацию в 'var json'. – nponeccop
А, я вижу. Поэтому 'bar' рассчитывается на основе' foo'. Подход onValues работает из-за того, как обновляется атомарность свойств. Результат из «дерева комбинации» свойств будет атомарным, но внутри «дерева» нет атомарности. Таким образом, ваши функции комбинатора могут быть вызваны и для недопустимых комбо. – raimohanska
Итак, у меня нет ответа, готового для вас в то время. Я думаю о том, чтобы добавить какой-то способ указать, что какой-то комбинатор нужно вызывать только для действительных (с атомарным обновлением) комбо ... – raimohanska