Reputation: 1662
I have recently built an single-page ASP.NET MVC 3 with a JS/jQuery UI (on top of the view's HTML), the general idea of the Javascript work is below. I am encountering issues with GC not properly freeing memory and leaving a large number of elements (24,000 for the biggest form, 15-20k, and 1k depending on which form is loaded/unloaded) in Detached DOM (viewable in Chrome's Developer tools Heap Profiler).
var MainApp = function () {
var meBase = this;
this.activeObject = undefined;
this.someFunc = function (val1, val2, etc) {
//Some operation here
}
this.GetView(x, y, z)
{
if (meBase.activeObject != null) {
meBase.BustActive(x, y, z);
} else {
if (condition) {
//Load static html via $.get
} else {
switch (activeObjectSelector) {
case CASEHERE:
self.activeObject = new SomeObject();
self.activeObject.BeginInit();
break;
case .....
}
}
}
}
this.BustActive = function (x, y, z) {
if (meBase.activeObject.Destroy()) {
meBase.activeObject = null;
meBase.GetView(x, y, z);
}
}
}
var SomeObject = function () {
var meBase = this;
this.Bindings = [];
this.Container = "#somecontainer";
//Some Properties
this.Unbind = function () {
$("#Somecontainer .bound").each(function () {
if ($(this)["click"] && $.isFunction($(this)["click"])) {
$(this).unbind('click');
}
if ($(this)["blur"] && $.isFunction($(this)["blur"])) {
$(this).unbind('blur');
} if ($(this)["change"] && $.isFunction($(this)["change"])) {
$(this).unbind('change');
}
if ($(this)["mouseenter"] && $.isFunction($(this)["mouseenter"])) {
$(this).unbind('mouseenter');
} if ($(this)["mouseleave"] && $.isFunction($(this)["mouseleave"])) {
$(this).unbind('mouseleave');
}
});
//iterate through meBase.Bindings to remove any 'special' bindings such as 'live/die'
}
this.MapEvents = function () {
//For Example
$("#Somecontainer #element").click(meBase.SomeAction).addClass('bound');
// create object with removal function for 'special' bindings such as 'live/die'
// and push it into meBase.Bindings;
}
this.InitUI = function () {
//Setup tabs, datepickers, etc
}
this.Destroy = function () {
meBase.Unbind();
//remove object fields and methods
delete meBase.someProp;
$(meBase.Container).empty();
delete meBase.BeginInit;
delete meBase.InitUI;
delete meBase.MapEvents;
delete meBase.SomeAction;
delete meBase;
return true;
}
this.SomeAction = function () {
//Do something productive..hopefully
}
this.ProcessView = function (data) {
$("#MainContainer").fadeOut(150, "swing", function () {
$(this).empty().append(data);
});
}
this.LoadView = function () {
$.ajax({
url: '/somewhere/something',
type: 'GET',
success: meBase.ProccessView, error: SomeGlobalObject.LogAjaxError
});
}
this.BeginInit = function () {
//Load pages via ajax
meBase.LoadView();
meBase.InitUI();
meBase.MapEvents();
return true;
}
}
I have tried doing iterations with javascript to remove events and elements in .Destroy() function, and it substantially reduced the number of elements left in Detached DOM versus $(container).empty() or $(container).remove(). But my memory is never properly collecting back down, it just continually rises during each load/unload. There are drops at random intervals, but not the amount I would expect. Is it normal for so many elements to remain hung-up, or is there some fundamental issue with the way my code is functioning?
Thanks for taking the time to read this!
First post, please be gentle...
Upvotes: 4
Views: 3245
Reputation: 2907
I've also recently been building some single-page apps in .Net MVC3. I suspect your problems are arising because Microsoft, in their attempts to keep developers out of JS and in C#, mucks around with the Javascript and Jquery on your page pretty badly.
The best advice I can give you is that you need to ditch all of Microsoft's cruft, and build the html/js part of your app as though it were totally platform independent. This means that you'll mostly be using the M in the MVC, and you'll only need enough Cs to manage your Ms. If the View is all HTML and Javascript, life gets a lot simpler indeed. Here's how to get started:
Require and Spine have quickly become my favorite tools for building single-page apps. They give you some very powerful and flexible tools to help you manage the increased volume of Javascript code you'll be writing in any single-page app.
Once you've got your client-side code completely disconnected from Microsoft's attempts to ruin Javascript, then you can focus on your data, which should use JSON-based Rest Services in MVC3. You can get help with this here and here.
Good luck!
Upvotes: 1