KnockoutJS:具有大量可观察量的虚假回调

时间:2012-09-25 05:29:23

标签: knockout.js knockout-mapping-plugin knockout-2.0

我有一个使用KnockoutJS的页面,其中有大量的可观察量(这里约有35个相关,总共约60个)。我使用KO映射插件,但我不知道这是否与我的问题有关。

大多数(不是全部)可观察对象都绑定到输入字段。

用户可以将当前输入集保存到命名集,也可以从以前保存的集重新加载。有一个UI指示当前输入集是来自已保存的集,还是已编辑(未保存)的输入。

为了在编辑任何输入时更新“保存/加载输入”UI(我不关心哪一个),我订阅了所有相关的“输入”可观察数据。

这是我奇怪的问题:当订阅的observable的数量大约为25或更高时,我会在ko.applyBindings(...)调用的深处对我的回调函数进行虚假调用。

  • 当它发生时,只有一个虚假的回调
  • 报告的输入通常是我订阅的最后一个。
  • 如果我删除了足够的订阅以便我订阅大约25或更少,那么虚假回调就会消失。
  • 如果我通过了该限制并继续添加订阅,那么当我不断添加到列表中时,该呼叫将重新出现在不同的字段中。
  • 如果我订阅了所有输入,那么回调声称是__ko_mapping__的回调,这是荒谬的。

我必须假设我没有正确绑定订阅,或者KO或KO映射插件中存在一些导致订阅列表混乱的错误。到目前为止,我还无法跟踪问题。

订阅代码大致如下:

// markSavedInputsDirty(name) defined elsewhere
function registerCallbacks() {
    var data = viewModel.inputs;
    var member;
    for(member in data) {
        if (data.hasOwnProperty(member) && ko.isObservable(data[member])) {
            if(member /* ... not certain observables which I need to ignore */ ) {
                data[member].subscribe(function() {return markSavedInputsDirty(member)}, data[member]);
            }
        }
    }
}

(注意:上面的代码跟踪调用哪个成员,但仅作为调试辅助。当我们看到问题最初出现时,代码用于对所有可观察对象使用相同的回调函数(无currying) )

以前有人见过这样的事吗?

1 个答案:

答案 0 :(得分:0)

解决:

subscribe(...)电话的结束被搞砸了,正如@MichaelBest在评论中指出的那样。我虽然它在调用时会包含member的值,但它本身包含member(对象,所有调用都相同)。我所看到的是循环中member的最终值,这让我误入歧途。我不应该在午夜这样做。

以下是该行的正确实现:

data[member].subscribe(markSavedInputsDirty.bind(data[member], member));

一旦我获得了正确的诊断,一切都变得清晰:虚假的调用来自页面中value元素的<select>绑定。 Knockout内部需要确保所选<option>的值与viewModel的值完全相同(请参阅Knockout源代码中的ensureDropdownSelectionIsConsistentWithModelValue(...))。

在我的例子中,可观察值有3(数字),而选定的<option> - 自然 - 有“3”(字符串)。因此,Knockout将viewModel设置为选项的值,并触发通知。

因此,原始订阅(在我破坏尝试之前)是正确的,并且通知是合法的。我只需要交换周围的东西,所以我的监控代码在绑定之前没有任何影响。