«JScript - блок скриптов» и утечки памяти - Как правильно освободить ресурсы? - PullRequest
8 голосов
/ 20 февраля 2012

Я разместил несколько вкладок jquery в частичном представлении моего проекта. Я заметил в обозревателе решений Visual Studio, что во время отладки новая динамика JScript - script block генерируется каждый раз, когда я нажимаю на новую вкладку .

Это происходит, даже если я помещаю $('#mytabs .ui-tabs-hide').children().remove(); и $(".ui-tabs-hide").empty(); в событие show вкладок. Блоки сценариев содержат JavaScript, который я помещаю в частичные представления, вызываемые вкладками, поэтому каждый раз, когда я нажимаю на ранее нажатую вкладку, появляется новый блок JScript : очевидно, что это приводит к проблемам стабильности или утечкам памяти. .. например, я уже заметил, что некоторые таймеры и привязки не работают должным образом после двойной загрузки вкладки.

Я не знаю, вызвана ли проблема тем, как вызывать частичные представления, содержащие сценарии. Пожалуйста, будьте осторожны, как я устанавливаю действия контроллера (Индекс в примере).

Это моя среда: jquery 1.6.4 - jquery-ui 1.8.16 - IE 8.0.7601 Мне не удается отладить в других браузерах, потому что Visual Studio, кажется, не присоединяет их процессы и не показывает динамические данные ...

CONTROLLER

Вот пример действия, вызываемого вкладками

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

        return View(); 
    }

Вот некоторые части моих представлений и сценариев:

_Layout.cshtml

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

_TabsMenu.cshtml (частичное представление, содержащее меню вкладок)

 <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(); 
         }
     });
 });

(Я даже пытался поместить скрипт в div id, pheraps глупо, но я хотел посмотреть, был ли удален скрипт внутри DOM ... но ничего)

Index.cshtml

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

_Index.cshtml (частичное представление, содержащее повторяющийся объект jscript вопроса)

   <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]);

Обновлено

JScript - блок скрипта 1..N // это то, что я вижу внутри каждого блока JScript - скрипта во время отладки ... Я testint jqgrid. Это демоверсия с сайта Trirand .

     <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]);                

Ответы [ 3 ]

8 голосов
/ 28 февраля 2012

Сценарий, который анализируется браузером, отсутствует в DOM, и вы не можете «удалить» его - переменные по-прежнему определены, события по-прежнему связаны, методы по-прежнему там. Если вы поместите javascript в частичное представление, которое загружаете несколько раз, вы получите этот javascript несколько раз.

Вам нужно создать свой javascript, чтобы быть более устойчивым к этому. Если вы привязываете события к элементам за пределами динамической области - не делайте этого. Вы будете связывать их несколько раз. Переместите этот код куда-нибудь, он будет загружен только один раз. Старайтесь держать javascript в динамической области изолированно, чтобы он работал только с элементами, которые также находятся в динамической области.

Вы также можете защитить от нескольких определений с помощью простых проверок if, используя более ограниченные селекторы jquery и т. Д.

Без подробностей о том, что находится в этом повторяющемся блоке, я мало что могу предложить.

3 голосов
/ 04 марта 2012

Мне кажется, что ваша проблема в том, что каждый раз, когда вы загружаете вкладку, все скрипты в ней тоже загружаются, и, насколько я понимаю, вы ничего не можете с этим поделать, помните, что вы можете использовать серверный код для генерации этих сценариев, поэтому ASP.NET должен действовать так, как будто они все разные (так как они на самом деле могут быть).

Однако javascript - это сборка мусора, поэтому я не думаю, что те сценарии, которые вы видите, на самом деле занимают память пользователя, когда вы не отлаживаете, отладчик всегда будет отображать все, что было загружено, независимо от того, было ли оно собрано или нет (хотя Я не проверял это на самом деле).

Если вас беспокоит память, просто убедитесь, что вы не объявляете глобальные функции и переменные, которые никогда не будут собирать мусор (особенно в областях, которые перезагружаются), для этого просто окружите их

(функция () {

и

}) ();

Так что они находятся в анонимной функции, которая может быть собрана сборщиком мусора сразу после ее выполнения.

2 голосов
/ 04 марта 2012

Вам просто нужно собрать все скрипты на вкладках, в событии готовности документа.Приведенный ниже код находит все дочерние элементы сценария элемента, выполняет их, а затем уничтожает их, поэтому они не могут быть выполнены снова:

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;}
...