We're building a fairly large one-page-application with KnockoutJS as "data-handler".
The problem is that when changing model-data, the old models isn't disposed by the garbage collector (as it seems).
The application has about 12 different models with computed obserables that you can retreive relations with.
In the ViewModel I have a observable array for each of the model. Lets say I fill a array with 100 instances of a model. When I later want to change these 100 to 100 different instances the memory grows and it never goes down (I'm using Chrome and checking the in the Windows Task Manager).
The application is quite complex but I'll give some examples of what I'm doing (code is copied and simplified to only show some examples, some of the code might seem to be strange but its problably because I removed namespacing and other stuff).
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);
});
_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
};
})();
Department model
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;
};
Address model
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;
};
There are alot more code but what I'm looking for is a way to start finding the leak (I have tried to find it for some hours now). Is there something in my example that could cause it? Or has anyone else had this kind of problem? The app also has multiple custom bindings but I've tried to remove the HTML that uses the bindings and it seems that the "raw" javascript object is what taking up the memory.
If I'm changing the observable & computed variables in the models to functions that return a static value the objects seems to be disposed.