Performance 使用敲除映射插件面临性能问题
我有大约1100条记录的大数据集。该数据集被映射到一个可观察的数组,然后该数组被绑定到一个视图。由于这些记录经常更新,因此每次使用ko.mapping.fromJS帮助器都会更新可观察数组 这个特定的命令大约需要40秒来处理所有的行。用户界面只是在这段时间内锁定 这是代码-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;
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不包含在您的页面中
- 应该更快,因为它只做绝对必要的事情
if (a_path.length >= 2
&& a_path[a_path.length-1] == 'mapThisProperty'
&& a_path[a_path.length-2] == 'insideThisProperty')
result = ko.observable(a_what);