我们有一个SPA,可以通过AJAX获取小批量的项目,并使用它们来填充通过foreach绑定到DOM的淘汰赛observableArray。
当新数据到达时,我们使用removeAll()清除旧数组并推送新项目。使用Chrome配置文件工具,我们发现这会导致内存泄漏,并且数据和闭包的数量会悬空。泄漏越多,泄漏越大。
我们构建了一个简单的测试用例来演示该问题(请参阅此fiddle)。重现:
HTML:
<div data-bind="click:go,
text:(clickCount()==0)
? 'click once then take a heap snapshot'
: 'click me lots then take another heap snapshot to compare'"
style="cursor:pointer"></div>
<ul data-bind="foreach:array">
<div data-bind="text:$data.name"></div>
<div data-bind="text:$data.age"></div>
</ul>
使用Javascript:
var getJoes = function(){
var joes=[];
for(var i=0;i<10;i++)
{
var name="Joe";
var age=((Math.random()*10)+1)>>0;
joes.push({Name:name,Age:age});
}
return joes;
};
function viewModel(){
var self=this;
self.array = ko.observableArray();
self.clickCount=ko.observable(0);
self.go = function(){
self.clickCount(self.clickCount()+1);
self.array.removeAll();
var joes=getJoes();
joes.forEach(function(joe){
var joeObs = ko.observable({
name:ko.observable(joe.Name),
age:ko.observable(joe.Age)});
self.array.push(joeObs);
});
};
}
ko.applyBindings(new viewModel());
这是一个错误还是我们遗漏了什么?
答案 0 :(得分:1)
我正在弄乱你的小提琴,并注意到如果你推动具有可观察属性的vanilla对象而不是推动包裹在一个observable中的vanilla对象,问题就会消失:
joes.forEach(function(joe){
var joeObs = {
name:ko.observable(joe.Name),
age:ko.observable(joe.Age)};
self.array.push(joeObs);
});
我对此没有任何解释。所以我的答案更多的是一个问题......真正的区别是什么?为什么一个泄漏而另一个没有?
答案 1 :(得分:1)
我们从jsfiddle中取出测试用例,独立运行和宾果游戏 - 没有内存泄漏。呼。
似乎它比预期更多地参与舞蹈!