"JScript - script block" and memory leaks - How to free resources properly?

I put some jquery tabs inside a partial view of my project. I noticed in Visual Studio "Solution Explorer" that during debugging a new dynamic JScript - script block created JScript - script block every time I click on a new tab .

This happens even if I put $('#mytabs .ui-tabs-hide').children().remove(); and $(".ui-tabs-hide").empty(); inside show event tabs. Script blocks contain javascript, which I put inside partial views called by tabs, so every time I click on a tab previously pressed, a new JScript block appears : obviously this leads to stability or memory leak problems ... for example, I already noticed that some timers and snaps do not work properly after I double-loaded the tab.

I do not know if the problem is caused by calling partial views containing scripts. Please be careful how I set the actions of the controller (pointer in the example).

This is my environment: jquery 1.6.4 - jquery-ui 1.8.16 - IE 8.0.7601 I cannot debug other browsers because Visual Studio does not seem to attach its processes and does not show dynamic data ...

CONTROLLER

Here is an example of an action called by tabs

  public ActionResult Index() { if (Request.IsAjaxRequest()) return PartialView("_Index"); return View(); } 

Here are some parts of my views and scripts:

_Layout.cshtml

  .... <div id="body"> @Html.Partial("_TabsMenu"); </div> .... 

_TabsMenu.cshtml (partial view containing the tab menu)

  <div id="menutabs" class="content-wrapper"> <ul > <li>@Html.ActionLink("Home", "Index", "Home")</li> <li>@Html.ActionLink("Test", "Index", "Test")</li> ... </ul> </div> <script type="text/javascript"> $(function () { $('#menutabs').tabs({ cache: false, show: function (event, ui) { $('#menutabs .ui-tabs-hide').children().remove(); // the content is removed , but the script is still in memory $(".ui-tabs-hide").empty(); // the content is removed, but the script is still in memory }, select: function (event, ui) { $(window).unbind(); } }); }); 

(I even tried to put the script inside the div id, pheraps is stupid, but I wanted to see if the script was deleted inside the DOM ... but nothing)

Index.cshtml

  @{Html.RenderPartial("_Index");} 

_Index.cshtml (partial view containing a repeating jscript object of the question)

  <table id="list4"></table> <jQuery("#list4").jqGrid({ datatype: "local", height: 250, colNames:['Inv No','Date', 'Client', 'Amount','Tax','Total','Notes'], colModel:[ {name:'id',index:'id', width:60, sorttype:"int"}, {name:'invdate',index:'invdate', width:90, sorttype:"date"}, {name:'name',index:'name', width:100}, {name:'amount',index:'amount', width:80, align:"right",sorttype:"float"}, {name:'tax',index:'tax', width:80, align:"right",sorttype:"float"}, {name:'total',index:'total', width:80,align:"right",sorttype:"float"}, {name:'note',index:'note', width:150, sortable:false} ], multiselect: true, caption: "Manipulating Array Data"}); var mydata = [ {id:"1",invdate:"2007-10-01",name:"test",note:"note",amount:"200.00",tax:"10.00",total:"210.00"}, {id:"2",invdate:"2007-10-02",name:"test2",note:"note2",amount:"300.00",tax:"20.00",total:"320.00"}, {id:"3",invdate:"2007-09-01",name:"test3",note:"note3",amount:"400.00",tax:"30.00",total:"430.00"}, {id:"4",invdate:"2007-10-04",name:"test",note:"note",amount:"200.00",tax:"10.00",total:"210.00"}, {id:"5",invdate:"2007-10-05",name:"test2",note:"note2",amount:"300.00",tax:"20.00",total:"320.00"}, {id:"6",invdate:"2007-09-06",name:"test3",note:"note3",amount:"400.00",tax:"30.00",total:"430.00"}, {id:"7",invdate:"2007-10-04",name:"test",note:"note",amount:"200.00",tax:"10.00",total:"210.00"}, {id:"8",invdate:"2007-10-03",name:"test2",note:"note2",amount:"300.00",tax:"20.00",total:"320.00"}, {id:"9",invdate:"2007-09-01",name:"test3",note:"note3",amount:"400.00",tax:"30.00",total:"430.00"} ]; for(var i=0;i<=mydata.length;i++) jQuery("#list4").jqGrid('addRowData',i+1,mydata[i]); 

Update

JScript - script block 1..N // this is what I see inside each JScript - script block during debugging ... I am testint jqgrid. This is a demo from the Trirand website .

  <jQuery("#list4").jqGrid({ datatype: "local", height: 250, colNames:['Inv No','Date', 'Client', 'Amount','Tax','Total','Notes'], colModel:[ {name:'id',index:'id', width:60, sorttype:"int"}, {name:'invdate',index:'invdate', width:90, sorttype:"date"}, {name:'name',index:'name', width:100}, {name:'amount',index:'amount', width:80, align:"right",sorttype:"float"}, {name:'tax',index:'tax', width:80, align:"right",sorttype:"float"}, {name:'total',index:'total', width:80,align:"right",sorttype:"float"}, {name:'note',index:'note', width:150, sortable:false} ], multiselect: true, caption: "Manipulating Array Data"}); var mydata = [ {id:"1",invdate:"2007-10-01",name:"test",note:"note",amount:"200.00",tax:"10.00",total:"210.00"}, {id:"2",invdate:"2007-10-02",name:"test2",note:"note2",amount:"300.00",tax:"20.00",total:"320.00"}, {id:"3",invdate:"2007-09-01",name:"test3",note:"note3",amount:"400.00",tax:"30.00",total:"430.00"}, {id:"4",invdate:"2007-10-04",name:"test",note:"note",amount:"200.00",tax:"10.00",total:"210.00"}, {id:"5",invdate:"2007-10-05",name:"test2",note:"note2",amount:"300.00",tax:"20.00",total:"320.00"}, {id:"6",invdate:"2007-09-06",name:"test3",note:"note3",amount:"400.00",tax:"30.00",total:"430.00"}, {id:"7",invdate:"2007-10-04",name:"test",note:"note",amount:"200.00",tax:"10.00",total:"210.00"}, {id:"8",invdate:"2007-10-03",name:"test2",note:"note2",amount:"300.00",tax:"20.00",total:"320.00"}, {id:"9",invdate:"2007-09-01",name:"test3",note:"note3",amount:"400.00",tax:"30.00",total:"430.00"} ]; for(var i=0;i<=mydata.length;i++) jQuery("#list4").jqGrid('addRowData',i+1,mydata[i]); 
+8
jquery jquery-ui memory-leaks asp.net-mvc jquery-ui-tabs
source share
3 answers

The script that the browser parses is not in the DOM, and you cannot โ€œdeleteโ€ it - the variables are still defined, the events are still connected, the methods still exist. If you add javascript to the partial view that you reload, you will receive this javascript several times.

What you need to do is your javascript to be more resistant to this. If you bind events to elements outside the dynamic area - do not do this. You will bind them several times. Move this code somewhere, it will be downloaded only once. Try to keep javascript in an isolated dynamic region, so it only deals with elements that are also in the dynamic region.

You can also protect against multiple definitions with simple checks using jquery selectors that are more covered, etc.

Without the details of what's in this repeating block, I cannot offer.

+8
source share

It seems to me that your problem is that every time you load a tab, all scripts in it also load, and as far as I know, you can do nothing about it, remember that you can use server-side code to generate of these scenarios, so ASP.NET should act as if they are all different (since they may actually be).

However, javascript IS garbage is collected, so I donโ€™t think that these scripts that you see actually occupy the user's memory, when you are not debugging, the debugger will always show everything that has been loaded, regardless of whether it was collected by garbage or not (although I have not actually tested it).

If you are worried about memory, just make sure you don't declare global functions and variables that will never collect garbage (especially in areas that load), to do this, just surround them

(function () {

and a

}) ();

So, they are in an anonymous function, which can be collected with garbage immediately after its execution.

+3
source share

You just need to collect all the scripts on the tabs in the document ready event. In the code below, find all the script children of the element, execute them, and then destroy them so that they cannot be executed again:

 function GlobalEvalScriptAndDestroy(element) { var allScriptText = CollectScriptAndDestroy(element); jQuery.globalEval(allScriptText);} function CollectScriptAndDestroy(element) { var allScriptText = ""; if (element.tagName == "SCRIPT") { allScriptText = element.text; $(element).remove(); } else { var scripts = $(element).find("script"); for (var i = 0; i < scripts.length; i++) { allScriptText += scripts[i].text; } scripts.remove(); } return allScriptText;} 
+2
source share

All Articles