Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 使用敲除映射插件面临性能问题_Performance_Knockout.js_Knockout Mapping Plugin - Fatal编程技术网

Performance 使用敲除映射插件面临性能问题

Performance 使用敲除映射插件面临性能问题,performance,knockout.js,knockout-mapping-plugin,Performance,Knockout.js,Knockout Mapping Plugin,我有大约1100条记录的大数据集。该数据集被映射到一个可观察的数组,然后该数组被绑定到一个视图。由于这些记录经常更新,因此每次使用ko.mapping.fromJS帮助器都会更新可观察数组 这个特定的命令大约需要40秒来处理所有的行。用户界面只是在这段时间内锁定 这是代码- var transactionList = ko.mapping.fromJS([]); //Getting the latest transactions which are around 1100 in number;

我有大约1100条记录的大数据集。该数据集被映射到一个可观察的数组,然后该数组被绑定到一个视图。由于这些记录经常更新,因此每次使用ko.mapping.fromJS帮助器都会更新可观察数组

这个特定的命令大约需要40秒来处理所有的行。用户界面只是在这段时间内锁定

这是代码-

var transactionList = ko.mapping.fromJS([]);

//Getting the latest transactions which are around 1100 in number;
var data = storage.transactions();

//Mapping the data to the observable array, which takes around 40s
ko.mapping.fromJS(data,transactionList)

有解决办法吗?还是我应该选择网络工作者来提高性能?

我在映射插件时也遇到了同样的问题。淘汰小组表示,映射插件不适用于大型阵列。如果您必须将如此大的数据加载到页面,那么很可能是系统设计不当

解决此问题的最佳方法是使用服务器分页,而不是在页面加载时加载所有数据。如果您不想更改应用程序的设计,有一些变通方法可以帮助您:

  • 手动映射阵列:

    var data = storage.transactions();
    var mappedData = ko.utils.arrayMap(data , function(item){
        return ko.mapping.fromJS(item);
    });
    
    var transactionList = ko.observableArray(mappedData);
    
  • 异步映射数组。我编写了一个函数,该函数在另一个线程中按部分处理数组,并向用户报告进度:

    function processArrayAsync(array, itemFunc, afterStepFunc, finishFunc) {
        var itemsPerStep = 20;
    
        var processor = new function () {
            var self = this;
            self.array = array;
            self.processedCount = 0;
            self.itemFunc = itemFunc;
            self.afterStepFunc = afterStepFunc;
            self.finishFunc = finishFunc;
            self.step = function () {
                var tillCount = Math.min(self.processedCount + itemsPerStep, self.array.length);
                for (; self.processedCount < tillCount; self.processedCount++) {
                    self.itemFunc(self.array[self.processedCount], self.processedCount);
                }
    
                self.afterStepFunc(self.processedCount);
                if (self.processedCount < self.array.length - 1)
                    setTimeout(self.step, 1);
                else
                    self.finishFunc();
            };
        };
    
        processor.step();
    };
    
    您也可以尝试其他映射库:。它应该比映射插件快


    我选择了第二个选项。

    我还想到了一个解决方案,如下所示,这样使用的代码量更少-

    var transactionList = ko.mapping.fromJS([]);
    
    //Getting the latest transactions which are around 1100 in number;
    var data = storage.transactions();
    
    //Mapping the data to the observable array, which takes around 40s
    // Instead of - ko.mapping.fromJS(data,transactionList)
    var i = 0;
    
    //clear the list completely first
    transactionList.destroyAll();
    
    //Set an interval of 0 and keep pushing the content to the list one by one.
    var interval = setInterval(function () {if (i == data.length - 1 ) {
                                            clearInterval(interval);}
    
                                        transactionList.push(ko.mapping.fromJS(data[i++]));
                                    }, 0);
    
    是knockout.mapping的替代品,它在为类似这样的大型对象阵列创建viewmodels时速度显著加快。您应该注意到性能显著提高


    映射不是魔法。在大多数情况下,这个简单的递归函数就足够了:

    function MyMapJS(a_what, a_path)
    {
        a_path = a_path || [];
    
        if (a_what != null && a_what.constructor == Object)
        {
            var result = {};
            for (var key in a_what)
               result[key] = MyMapJS(a_what[key], a_path.concat(key));
            return result;
        }
    
        if (a_what != null && a_what.constructor == Array)
        {
            var result = ko.observableArray();
            for (var index in a_what)
               result.push(MyMapJS(a_what[index], a_path.concat(index)));
            return result;
        }
    
        // Write your condition here:
        switch (a_path[a_path.length-1])
        {
            case 'mapThisProperty':
            case 'andAlsoThisOne':
                result = ko.observable(a_what);
                break;
            default:
                result = a_what;
                break;
        }
        return result;
    }
    
    上面的代码在对象层次的任何级别都可以从映射ThisProperty以及其他属性中进行观察;其他属性保持不变。对于值所在的级别(深度),可以使用a_路径.length表示更复杂的条件,或者使用a_路径的更多元素。例如:

    if (a_path.length >= 2 
      && a_path[a_path.length-1] == 'mapThisProperty' 
      && a_path[a_path.length-2] == 'insideThisProperty')
        result = ko.observable(a_what);
    
    您可以在条件中使用a_what
    类型,例如,使所有字符串可见。 您可以忽略某些属性,并在某些级别插入新属性。 或者,您甚至可以省略路径。等等

    优点是:

    • 可定制(比knockout.mapping更容易)
    • 足够短,可以复制粘贴它,并在需要时为不同的对象编写单独的映射
    • 较小的代码knockout.mapping-latest.js不包含在您的页面中
    • 应该更快,因为它只做绝对必要的事情

    我需要一些时间来看看它是否真的提高了性能。你能给出一个示例代码来描述我如何在我的案例中使用它吗?非常有趣的解决方案。创建一个JsPerf看看它能快多少,这会很有趣。@billy编辑文章时请小心。更改原始问题的编码样式被视为与更改帖子的含义相同。我回滚了编辑
    if (a_path.length >= 2 
      && a_path[a_path.length-1] == 'mapThisProperty' 
      && a_path[a_path.length-2] == 'insideThisProperty')
        result = ko.observable(a_what);