Recolección de basura de oyentes de events innecesarios en javascript

Estoy construyendo una aplicación web de una sola página. Esto significa que durante un período de time obtengo nuevos elementos DOM, elimino los innecesarios. Por ejemplo, cuando obtengo un formulario nuevo, simplemente reemploop los contenidos de un div específico con ese formulario HTML y también configuro oyentes únicos para los elementos de este formulario. Después de un time, reemploop el contenido de este formulario con una nueva instancia de formulario (con diferentes ID).

Configuré los oyentes del evento nuevamente para este nuevo formulario. Ahora, la forma anterior ya no forma parte del DOM, por lo que los elementos DOM se deben recolectar automáticamente. También estoy esperando que desaparezcan las funciones del oyente que apuntan a los elementos eliminados del DOM.

Sin embargo, el siguiente perfil recostackdo de Chrome sugiere que mi count de oyentes aumenta con el time. ¿Puedes decirme por qué es así? Intenté hacer clic en el button "Recoger basura". Pero este es el perfil que obtengo ¿Hay algún problema con la forma en que estoy desarrollando mi aplicación? ¿Hay algún problema? Si es así, ¿cómo debería solucionarlo?

Instantánea de Chrome de mi aplicación web durante unos minutos

En caso de que importe, estoy usando el lenguaje de templates JSP con jquery, jquery-ui y algunos otros complementos. Así es como se ven los fragments dynamics que agrego / elimino en mi página.

<script> $(document).ready(function() { $("#unique_id").find(".myFormButton").button().click( function() { $.ajax({url: "myurl.html", success: function(response) { console.log(response); } }); }); }); </script> <div id="unique_id"> <form> <input name="myvar" /> <button class="myFormButton">Submit</button> </form> </div> 

Actualizar

Si desea ver el código actual, aquí está la parte relevante. Este enlace muestra que cuando se presiona el button borrar, se llama a la function clearFindForm que relabel de manera efectiva el contenido (fragment HTML) usando una request ajax y reemplaza todo el div en este jsp con el contenido recuperado. La function refetchContent funciona de la siguiente manera: Aquí está el enlace al código en caso de que ayude a dar una mejor respuesta.

 function refetchContent(url, replaceTarget) { $.ajax({ url: url, data: {}, type: "GET", success: function (response) { replaceTarget.replaceWith(response); }, error: function (response) { showErrorMessage("Something went wrong. Please try again."); } }); } 

3 Solutions collect form web for “Recolección de basura de oyentes de events innecesarios en javascript”

Si bien jQuery es muy bueno para eliminar los detectores de events de los elementos DOM que se eliminan a través de sus methods (incluido .html () – solo lee la API: http://api.jquery.com/html/ ) – no eliminará el evento oyentes de elementos DOM que aún pueden tener una reference a ellos en un tree DOM aislado.

Por ejemplo, si haces algo como esto:

 $.ajax({ .... }) .done(function(response,status,jqXHR) { //create a detached DOM tree form = $(response) //add an event listener to the detached tree form.find('#someIDInTheResponse').on('submit',function() { }); //add the form to the html $('#someID').html(form); }); //at some other point in the code $('#someIDInTheResponse').remove(); 

Tenga en count que en el ejemplo anterior, a pesar de que eliminó el elemento del DOM, el oyente no se eliminará de la memory. Esto se debe a que el elemento todavía existe en la memory en un tree DOM separado accesible a través de la variable global "forma" (esto es porque no creé usar "var" para crear el tree DOM inicial separado en el scope de la function completada. … hay algunos matices y jQuery no puede reparar el código incorrecto, solo puede hacerlo mejor.

2 otras cosas:

Hacer todo lo que esté dentro de las devoluciones de llamadas u oyentes de events (como hacer clic en un button) se convierte en un verdadero código de spaghetti realmente rápido y se vuelve inmanejable con bastante rapidez. Intente separar la lógica de la aplicación de la interacción de la interfaz de usuario. Por ejemplo, no use devoluciones de llamada para hacer clic en events para realizar un montón de lógica, use devoluciones de llamada para hacer clic en events para llamar a funciones que realizan un montón de lógica.

En segundo lugar, y algo less importante, (me complacen los comentarios sobre esta perspectiva a través de los comentarios) Considero que 30 MB de memory es una línea de base bastante alta para una aplicación web. Tengo una aplicación web de Google Maps bastante intensa que llega a los 30 MB después de una hora de uso intensivo y realmente notas que empiezas a notar su lentitud cuando lo haces. Dios sabe cómo actuaría si alguna vez alcanza los 60MB. Estoy pensando que IE <9 sería prácticamente inutilizable en este momento, aunque, como dije, agradezco los comentarios de otras personas sobre esta idea.

Me pregunto si simplemente no está desvinculando / eliminando los escuchas de events previamente vinculados cuando reemplaza fragments?

Miré brevemente las secciones específicas de código a las que se vinculó en su pregunta actualizada, pero no vi ningún enlace de escucha de events distinto de lo que está haciendo en documento listo, así que supongo que está haciendo un enlace adicional cuando lo reemplaza el documento se fragmenta. No soy un experto en jQuery, pero en general vincular o asignar escuchas de events adicionales no reemplaza automáticamente a los oyentes de events asignados / asignados previamente.

Mi punto es que debe ver si está haciendo la vinculación a través de "click ()" (o mediante algún otro método) a los elementos existentes sin desvincular primero el oyente de events existente.

Puede echar un vistazo a la respuesta de moff a esta pregunta , que proporciona un ejemplo para hacer clic, específicamente.

No puedo agregar un comentario debido a la reputación, pero para responder a lo que Adam está diciendo …

Para resumir el caso que presenta Adam, es potencialmente nada que ver con jQuery, el problema puede estar dentro del Javascript normal. Sin embargo, no presenta el código suficiente para que alguien realmente llegue al background del problema. Su uso de la encapsulación de ámbito puede ser perfectamente correcto y el problema puede ser otro.

Le recomendaría que busque herramientas para encontrar la causa de las pérdidas de memory (por ejemplo, visualizar / atravesar todo el object / scope / tree de reference / function, etc.).

Una cosa a tener en count con jQuery son los complementos y las inserciones globales en el DOM. He visto muchas librerías JS, no solo jQuery, no proporcionan destructores y methods de limpieza. Los peores delincuentes son a menudo cosas con windows emergentes y windows emergentes como selectores de date, dialogs, etc. que tienen la desagradable costumbre de agregar divisiones de capa y elementos similares en el cuerpo sin eliminarlos después.

Algo que se debe tener en count si muchas personas llegan a hacer construcciones pero no manejan la destrucción, especialmente en JS, ya que esperan incluso en este día y en la edad que usted esté atendiendo páginas web normales. También debe verificar los complementos para methods de destrucción porque no todos se engancharán en un evento de eliminación. Los events también se usan de manera complicada en jQuery por otros, por lo que un manejador no autorizado podría estar deteniendo la ejecución de los siguientes events de limpieza.

En resumen, jQuery es una buena biblioteca robusta, pero ten en count que el hecho de que alguien dependa de ella no significa que henetworkinge la calidad de jQuery.

Por curiosidad … ¿has revisado a los oyentes en document.ready? Tal vez necesitas GC manualmente.

  • JavaScript nueva palabra key y gestión de memory
  • Errores de gestión de memory Javascript?
  • ¿Cómo se recolectan los objects anónimos en JavaScript?
  • ¿Recostackrá este código JavaScript basura como yo esperaba?
  • Manejadores de events, cierres y recolección de basura en Javascript
  • Uso de memory Javascript en for loop
  • ¿Cómo detectar las asignaciones de memory que desencadenan la recolección de basura en JavaScript?
  • Al usar React ¿Es preferible utilizar funciones de flecha de grasa o funciones de unión en el constructor?
  • Cómo depurar / analizar pausas de GC extremadamente largas en Node.js / V8
  • Fuga de memory de cierre de JavaScript
  • ¿Patrón para loops sin asignación en JavaScript?
  • Cierres de JavaScript relativos a variables no referencedas
  • Función de function anidada Javascript
  • Javascript tiene muchos buenos JS marco (como Node.js AngularJS Vue.js React.js) es el mejor lenguaje de script.