2012-02-20 17 views
8

Ho inserito alcune schede jquery all'interno di una vista parziale del mio progetto. Ho notato da "Solution Explorer" di Visual Studio che durante il debug viene generata una nuova dinamica JScript - script block ogni volta che faccio clic su una nuova scheda."JScript - blocco di script" e perdite di memoria - Come liberare correttamente le risorse?

Ciò accade anche se inserisco $('#mytabs .ui-tabs-hide').children().remove(); e $(".ui-tabs-hide").empty(); all'interno dell'evento show delle schede. I blocchi di script contengono javascript che inserisco nelle viste parziali chiamate da tab, quindi ogni volta che faccio clic su una scheda precedentemente cliccata, appare un nuovo blocco JScript: è evidente che questo porta a problemi di stabilità o perdite di memoria ... per Ad esempio, ho già notato che alcuni timer e associazioni non funzionano correttamente dopo aver caricato due volte una scheda.

Non so se il problema è causato dal modo in cui chiamate le viste parziali contenenti gli script. Si prega di fare attenzione a come imposto le azioni del controller (Indice nell'esempio).

Questo è il mio ambiente: jQuery 1.6.4 - jquery-ui 1.8.16 - IE 8.0.7601 non posso avere successo per eseguire il debug con altri browser, perché Visual Studio non lo fa sembra collegare i loro processi e non lo fa mostrare i dati dinamici ...

CONTROLLER

Ecco un esempio di azione chiamato dal linguette

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

     return View(); 
    } 

Ecco alcune parti del mio punto di vista e script:

_Layout.cshtml

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

_TabsMenu.cshtml (Parziale vista contenente il menu schede)

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

(ho anche provato a inserire script all'interno di div id, gli sheraps sono stupidi, ma volevo vederli f lo script all'interno del DOM è stato rimosso ... ma nulla)

Index.cshtml

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

_Index.cshtml (vista parziale contenente l'oggetto jscript ripetuto della domanda)

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

Aggiornato

JScript - blocco di script 1..N // questo è ciò che vedo all'interno di ogni blocco di script JScript, durante il debugging ... Sono testint jqgrid. Questo è un demo from Trirand's site.

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

è possibile profilo javascript nella maggior parte delle moderne console del browser che sarebbe un test molto migliore rispetto a un IDE. Se il tuo test jQgrid è direttamente da una demo, senza modifiche ... Sospetto che VS ti dia brutte informazioni. Se è un codice modificato, è probabile che tu abbia impostato una sorta di ricorsione eccessiva – charlietfl

risposta

8

Script che è analizzato da un browser non è nel DOM, e non si può "rimuovere" esso - le variabili sono ancora definiti, gli eventi sono ancora legati, i metodi sono ancora lì. Se metti javascript in una vista parziale che carichi ripetutamente, avrai ripetutamente quel javascript.

Quello che devi fare è creare il tuo javascript per essere più resiliente a questo. Se stai vincolando eventi a elementi esterni all'area dinamica, non farlo. Li vincolerai più volte. Sposta quel codice da qualche parte, verrà caricato solo una volta. Cerca di mantenere il javascript nell'area dinamica isolata in modo che si occupi solo degli elementi che si trovano anche nell'area dinamica.

È inoltre possibile proteggere più definizioni con semplice se i controlli, utilizzando i selettori jQuery che sempre di ambito, ecc

Senza i dettagli di ciò che è in quel blocco ripetuto, non c'è molto che posso offrire.

+0

THX @bhamlin! Inserisco il codice javascript coinvolto all'interno della domanda. Potresti darmi un aiuto per evitare questo cattivo comportamento e isolare il problema, per favore? Ogni modifica alla scheda carica un nuovo script in memoria. Eviterei questo e penso che questo possa aiutare anche gli altri. Grazie mille! – Larry

+1

Sto indovinando che 'list1' dovrebbe essere' ticketgrid' e 'pager1' dovrebbe essere' jqpager'. Detto questo, non c'è nulla di intrinsecamente sbagliato nel caricare il blocco di script ogni volta. Se c'è un comportamento strano, potrebbe avere qualcosa a che fare con il modo in cui jqGrid è implementato, il che è probabilmente al di fuori dello scopo di questa domanda. Se si desidera caricare meno script ogni volta, è possibile inserire tale blocco di codice in Index.cshtml come funzione e limitarsi a chiamarlo _Index.cshtml, passando nell'elenco e agli elementi del cercapersone su cui operare. – bhamlin

+0

Hai ragione. Era un rifiuto. Ho corretto i nomi e ho aggiunto un altro esempio con dati statici, in modo che tutti possano testarli e riprodurli. So che non c'è niente di sbagliato caricando lo script ogni volta, ma il problema, come ho detto, è che ** lo script non viene mai scaricato **. Inoltre, ** tutto il codice è qui, e tutti potrebbero testare e riprodurre il comportamento **. JqGrid è molto semplice come implementazione, quindi sfortunatamente non è questo il punto del problema, penso. – Larry

2

È sufficiente raccogliere tutti gli script all'interno delle schede, nell'evento pronto per il documento. Il codice qui sotto trovare tutti i bambini di script di un elemento, li esegue e poi distruggerli, in modo che non possa essere eseguito di nuovo:

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;} 
+0

THX Francesco. Colleziono già degli script nell'evento pronto per il documento. Ho letto anche la seguente risposta di Eduardo, che dice che probabilmente gli script sono GC ... grazie anche per gli script. Ho già fatto '$ ('# menutabs .ui-tabs-hide'). Children(). Remove();' e '$ (". Ui-tabs-hide "). Empty();' su ogni scheda mostra e funziona almeno per html. Non pensi che dovrebbe essere abbastanza? Grazie ancora! – Larry

+0

Scusa Francesco, vorrei provare la tua soluzione. Potresti dirmi dove devo inserire il codice e come chiamarlo? Suppongo di dover chiamare l'evento show delle schede. THX – Larry

+0

No no. Fatelo sul div originale in cui applicate il plugin tabs prima di applicare il plug-in ... cioè nell'evento pronto per il documento. In questo modo, quando la scheda viene creata, lo script è già stato rimosso ... in questo modo si è sicuri che la loro presenza non interferirà con il plug-in –

3

Mi sembra come il vostro problema è che ogni volta che si carica una scheda, tutti i anche gli script vengono caricati e, per quanto mi riguarda, non c'è nulla che tu possa fare al riguardo, ricorda che puoi usare il codice lato server per generare quegli script in modo che ASP.NET debba agire come se fossero tutti diversi (dal momento che possono essere effettivamente).

Tuttavia, javascript È garbage collection quindi non penso che quegli script che vedi stiano effettivamente occupando la memoria dell'utente quando non esegui il debug, il debugger mostrerà sempre tutto ciò che è stato caricato indipendentemente dal fatto che sia stato garbage collector o no (anche se in realtà non l'ho provato).

Se la preoccupati per la memoria, basta assicurarsi che non stai dichiarando funzioni globali e le variabili che sarà mai garbage collection (specialmente in ambiti che ottengono Reloaded), per fare questo, basta circondarsi con un

(function() {

e

})();

In modo che siano in una funzione anonima che può essere raccolta automaticamente dopo che è stata eseguita.

+0

THX Eduardo. Le tue supposizioni su GC mi calmano, non c'è modo di essere sicuro, potresti darmi dei suggerimenti su come testare, per favore? – Larry

+0

Ho trovato questo link su javascript memory leaks [link] (http://www.javascriptkit.com/javatutors/closuresleak/index.shtml), utilizza Windows resource manager per guardare la memoria. –

+0

Sfortunatamente, il meglio che posso pensare è mettere un javascript con una grande stringa nella scheda, automatizzare il passaggio di schede/clic fino a quando non è soddisfatto, controllare il gestore delle risorse. –

Problemi correlati