我们正在使用KnockoutJS构建一个相当大的单页应用程序作为“数据处理程序”。
问题在于,在更改模型数据时,旧模型不会被垃圾收集器处理(看起来如此)。
该应用程序有大约12种不同的模型,具有计算的obserables,你可以检索与...的关系。
在ViewModel中,我为每个模型都有一个可观察的数组。让我们说我用100个模型实例填充一个数组。当我后来想要更改这100到100个不同的实例时,内存会增长并且永远不会下降(我正在使用Chrome并在Windows任务管理器中检查)。
应用程序非常复杂但我会给出一些我正在做的例子(代码被复制并简化为仅显示一些示例,一些代码可能看起来很奇怪,但可能是因为我删除了命名空间和其他的东西)。
视图模型:
var ViewModel = (function () {
var _departments = ko.observableArray(),
_addresses = ko.observableArray();
var UpdateData = function (data) {
if (typeof data.departments != 'undefined') {
var mappedData = ko.utils.arrayMap(data.departments, function(item) {
return new Department(item);
});
_departments(mappedData);
}
if (typeof data.addresses != 'undefined') {
var mappedData = ko.utils.arrayMap(data.addresses , function(item) {
return new Address(item);
});
_addresses (mappedData );
}
};
return {
departments: _departments,
addresses: _addresses,
UpdateData: UpdateData
};
})();
部门模型
var Department = function (data) {
var Department = {
Id: ko.observable(data.ClusterId),
Number: ko.observable(data.Number),
Name: ko.observable(data.Name)
};
var Addresses = ko.computed(function () {
return ko.utils.arrayFilter(ViewModel.addresses(), function (address) {
return address.DepartmentId() === Department.Id();
}).sort(function (a, b) {
return a.Number() < b.Number() ? -1 : 1;
});
}, Department);
var Update = function (data) {
Department.Id(data.Id);
Department.Number(data.Number);
Department.Name(data.Name);
};
$.extend(Department, {
Addresses: Addresses,
Update: Update
});
return Department;
};
地址模型
var Address = function (data) {
var Address = {
Id: ko.observable(data.Id),
Number: ko.observable(data.Number),
Text: ko.observable(data.Text),
DepartmentId: ko.observable(data.DepartmentId)
};
var Department = ko.computed(function () {
return ko.utils.arrayFirst(ViewModel.departments(), function (item) {
return item.Id() == Address.DepartmentId();
});
}, Address);
var Update = function (data) {
Address.Id(data.Id);
Address.Number(data.Number);
Address.Text(data.Text);
Address.DepartmentId(data.DepartmentId);
};
$.extend(Address, {
Department: Department,
Update: Update
});
return Address;
};
还有更多的代码,但我正在寻找的是一种开始发现泄漏的方法(我已经尝试找几个小时了)。我的例子中有什么东西可以导致它吗?或者有其他人有过这种问题吗?该应用程序还有多个自定义绑定,但我试图删除使用绑定的HTML,似乎“原始”javascript对象占用了内存。
如果我要更改可观察的&amp;将模型中的变量计算为返回静态值的函数,这些函数似乎处理了对象。
答案 0 :(得分:4)
每个computed's
和Department
中的Address
将保留对viewmodel的订阅,直到您更换部门和地址为止。例如,我希望这会泄漏内存:
ViewModel.UpdateData({ departments: [ /* some new departments */ ] });
ViewModel.UpdateData({ departments: [ /* some new departments */ ] });
ViewModel.UpdateData({ departments: [ /* some new departments */ ] });
ViewModel.UpdateData({ departments: [ /* some new departments */ ] });
ViewModel.UpdateData({ departments: [ /* some new departments */ ] });
ViewModel.UpdateData({ departments: [ /* some new departments */ ] });
ViewModel.UpdateData({ departments: [ /* some new departments */ ] });
ViewModel.UpdateData({ departments: [ /* some new departments */ ] });
在这种情况下,所有“旧”部门仍将绑定到您的ViewModel.Addresses
。更改Addresses
应该释放内存:
ViewModel.UpdateData({ addresses: [ /* some new addresses */ ]});
// all the old departments should get GC'd now.
解决此问题的一种方法是修改ViewModel
以便在删除之前处置旧对象:
var ViewModel = (function () {
var _departments = ko.observableArray(),
_addresses = ko.observableArray();
var UpdateData = function (data) {
if (typeof data.departments != 'undefined') {
var mappedData = ko.utils.arrayMap(data.departments, function(item) {
return new Department(item);
});
// dispose of the computeds in the old departments
ko.utils.arrayForEach(_departments(), function (d) { d.Addresses.dispose(); });
_departments(mappedData);
}
if (typeof data.addresses != 'undefined') {
var mappedData = ko.utils.arrayMap(data.addresses , function(item) {
return new Address(item);
});
// dispose of the computeds in the old addresses
ko.utils.arrayForEach(_addresses(), function (a) { a.Department.dispose(); });
_addresses (mappedData );
}
};
return {
departments: _departments,
addresses: _addresses,
UpdateData: UpdateData
};
})();
阅读Knockout Computed Documentation。具体滚动到底部并阅读dispose
的文档。如果要删除它们,请确保您创建的任何计算的dispose
,但是它们所依赖的可观察量不会被删除。