依赖观察值中的大型数组 - 级联

时间:2012-01-30 21:21:10

标签: javascript jquery algorithm knockout.js

我正在使用Knockout JS,因为业务需求要求大多数(如果不是全部)逻辑由于低带宽用户而在浏览器中处理。到目前为止,除了一个问题外,它的确很棒。

我使用了许多包含级联逻辑的多选下拉列表。我有8个列表处理分层数据并改变子列表中的可选选项。

这一切都很好,直到我到达底部的2个列表,这些列表可能包含3000个项目,具体取决于父列表选择(特别是当单击“全选”时)。

问题是,在IE中,我正在运行脚本警告消息,我需要摆脱它。这是一些代码:

viewModel.BottomLevelList= ko.dependentObservable(function () {
        if (this.ParentList().length === 0) { //nothing selected
            return [];
        }          
        var result = [];
        var i = self.longMasterList.length;
        var currentId = 0;
        while (i--) {
           //psuodo code:
           //this.ParentList().Contains(loop-item) then
               //put in return list based on some further logic
           //else continue
        }

        return result;


    }, viewModel);

我尝试过使用SO中的各种setTimeout技术来打破大型阵列并立即将控制权返回给浏览器,但没有成功。结果永远不会返回和/或observable似乎分离自己在UI中留下一个空列表。

如果我需要使用AJAX,我会这样做,但这是最后的选择,并希望将其保留在客户端。

所以我的问题归结为:

  • 如何处理大型数据集(在Knockout JS依赖的observables和级联列表的上下文中)停止长时间运行的脚本警告
  • 我可以/应该在这种情况下使用一些惯用的JavaScript技术
  • 我在这里看不到树木了吗?!

非常感谢您的帮助

1 个答案:

答案 0 :(得分:6)

我建议您优化dependentObservable。 当您读取任何observable时,Knockout会在Dependency Manager中向它注册一个依赖项。它包含非常简单的代码:

function registerDependency(observable) {
    if (ko.utils.arrayIndexOf(dependencies, observable)) {
        dependencies.push(observable);
    }
}

我可以在你的伪代码中看到你正在while循环中访问this.ParentList()。这意味着registerDependency将被调用3000次,dependencies数组将被扫描3000次,这对IE来说是不好的(因为它没有内置的Array.indexOf方法)。

所以我的第一个建议是:在循环之前阅读所有可观察量。

如果它没有用,我建议你继续使用setTimeout()。这有点棘手。请查看此示例:http://jsfiddle.net/romanych/4KGAv/3/

我定义了asyncObservable。您应该传递一个包含dependentObservable的所有依赖项的数组。调用ko.toJS时,将打开所有可观察对象。然后我们使用dependencies数组中枚举的参数调用传递的回调函数。此函数将被评估为异步。

我已将此代码包装到ko.dependentObservable中,以便在loader

中传递的传递元素的任何更改上重新评估dependencies回调

<强>更新: 我的代码在这个问题上过于复杂。 throttle extender会做到这一点。请查看此示例:http://jsfiddle.net/romanych/JNwhb/1/