Knockout Observable Array变得指数级变慢

时间:2013-09-16 23:11:19

标签: knockout.js breeze bigdata

我想在这里找到一个好的答案,而不是寻找任何答案,“你试过X吗?”,宁愿有一个知识渊博的答案。

我有一个可观察的数组,我用它来填写图表。可观察数组最多可包含10k个POJO,这些POJO是从本地缓存中的Breeze.js中检索的。当我第一次出去从服务器获取数据,然后对本地缓存进行调用时,它几乎立即返回。

在下次通话中,它会以指数方式变慢。返回的对象不是每个可观察对象,也不包含observable,因为我正在执行Breeze查询,选择它们是POJO。问题是,当我返回并继续获得相同的数据集时,它们会继续变得越来越慢。几乎让我想到我在某种程度上在可观察数组中创建了内存泄漏。

在我看来 -

<h1>There are <span data-bind="text: chartData().length"></span> chart items</h1>

在我的视图模型中 -

var chartData = ko.computed(function () {
    var myArray = ko.observableArray();
    var params = { xmin: xMin(), xmax: xMax() };
    if (!initialized) { return myArray(); }
    datacontext.getData(myArray, params.xmin, params.xmax false);
    return myArray();
}).extend({ throttle: 2000 });

在执行查询的datacontext.js文件中 -

if (!forceRemote) {
    var thisData = manager.executeQueryLocally(query);
    myObservable([]);
    var myArray = myObservable();
    ko.utils.arrayPushAll(myArray, thisData);
    return myObservable.valueHasMutated();
}

我根据另一个SO.com问题的建议尝试了arrayPushAll和值变异,但它似乎没有设置myObservable([])然后将其设置为等于thisData更快。

由于数据集很大,我希望将其减少到尽可能少的重新计算。

我将xmin和xmax设置为params的原因是使计算依赖于两个observable ...

2 个答案:

答案 0 :(得分:3)

我自己发现Knockout在过滤时很慢,特别是在IE8上。不幸的是,这对我来说仍然是支持的浏览器:-(问题是我正在使用复杂的html模板过滤大型集合.IE8渲染引擎非常适合并且不断抛出“慢速运行脚本”警报。

我通过使用CSS'display'属性解决了这个问题。我为集合中的每个元素添加了一个可见的Observable,以及以下数据绑定。 (其中hidden是一个带有display:none;的css类)。

data-bind="css:{'hidden':visible()===false}"

然后你要做的就是遍历集合并根据需要设置属性。这对我的情况产生了巨大的影响。

答案 1 :(得分:2)

简化您的计算可观察量。很少有理由在计算的observable中创建一个observable。

var chartData = ko.computed(function () {
    var min = xMin(), max = xMax(); // ensure we have a dependency
    return !initialized ? [] : datacontext.getData(min, max, false);
}).extend({ throttle: 2000 });

查询只需要返回数据:

if (!forceRemote) {
    var thisData = manager.executeQueryLocally(query);
    return thisData;
}

编辑:

假设您已经加载了所有数据并将其存储在数组中,您计算​​的observable可以使用ko.utils.arrayFilter来计算过滤结果:

var chartData = ko.computed(function () {
    var min = xMin(), max = xMax(); // ensure we have a dependency
    return !initialized ? [] : ko.utils.arrayFilter(dataArray, function(item) {
        return item.x >= min && item.x <= max;
    });
});