jquery ajax memory-leaks

La llamada jQuery Ajax simple pierde memoria en Internet Explorer



memory-leaks (8)

Acabo de encontrar esto yo mismo. Al principio pensé que tenía algo que ver con la biblioteca de UI, pero luego desapareció después de que cambié en jQuery 1.5. para la versión 1.4.2 que estaba usando. (1.4.4 no parece solucionar el problema).

Creé una página web que hace una llamada Ajax cada segundo. En Internet Explorer 7, pierde mucha memoria (20 MB en unos 15 minutos).

El programa es muy simple. Simplemente ejecuta una función de JavaScript que realiza una llamada Ajax. El servidor devuelve una cadena vacía, y el código de JavaScript no hace nada con él. Uso setTimeout para ejecutar la función cada segundo, y uso Drip para ver la cosa.

Aquí está la fuente:

<html> <head> <script type="text/javascript" src="http://www.google.com/jsapi"></script> <script type="text/javascript"> google.load(''jquery'', ''1.4.2''); google.load(''jqueryui'', ''1.7.2''); </script> <script type="text/javascript"> setTimeout(''testJunk()'',1000); function testJunk() { $.ajax({ url: ''http://xxxxxxxxxxxxxx/test'', // The url returns an empty string dataType: ''html'', success: function(data){} }); setTimeout(''testJunk()'',1000) } </script> </head> <body> Why is memory usage going up? </body> </html>

¿Cómo tapar esta fuga? Tengo una aplicación real que actualiza una tabla grande de esta manera, pero si se deja desatendida, consumirá gigabytes de memoria.

Edit : está bien, así que después de algunas buenas sugerencias, modifiqué el código para:

<html> <head> <script type="text/javascript" src="http://www.google.com/jsapi"></script> <script type="text/javascript"> google.load(''jquery'', ''1.4.2''); google.load(''jqueryui'', ''1.7.2''); </script> <script type="text/javascript"> setTimeout(testJunk,1000); function testJunk() { $.ajax({ url: ''http://xxxxxxxxxxxxxx/test'', // The url returns an empty string dataType: ''html'', success: function(data){setTimeout(testJunk,1000)} }); } </script> </head> <body> Why is memory usage going up? </body> </html>

Sin embargo, no parecía hacer ninguna diferencia. No estoy haciendo nada con el DOM, y si hago un comentario fuera de la llamada Ajax, la pérdida de memoria se detiene. Así que parece que la fuga está totalmente en la llamada Ajax. ¿JQuery Ajax crea intrínsecamente algún tipo de referencia circular y, de ser así, cómo puedo liberarlo? Por cierto, no se filtra en Firefox.

Alguien sugirió ejecutar la prueba en otra máquina virtual y ver si los resultados son los mismos. En lugar de configurar otra máquina virtual, encontré una computadora portátil que ejecutaba XP Home con Internet Explorer 8. Presenta el mismo problema.

Probé algunas versiones anteriores de jQuery y obtuve mejores resultados, pero el problema no desapareció por completo hasta que abandoné Ajax en jQuery y seguí con Ajax más tradicional (y feo).


Aquí hay un link al error en jQuery, junto con esto como una solución sugerida para jQuery 1.4.2:

--- jquery-1.4.2.js 2010-04-08 12:10:20.000000000 -0700 +++ jquery-1.4.2.js.fixed 2010-04-08 12:10:38.000000000 -0700 @@ -5219,7 +5219,7 @@ // Stop memory leaks if ( s.async ) { - xhr = null; + xhr.onreadystatechange = null; xhr.abort = null; xhr = null; } } };

NOTA : Esto se ha corregido oficialmente en jQuery 1.4.4, por lo que su mejor opción es simplemente actualizar ahora.


El problema parece ser con jQuery 1.4 en Internet Explorer y, en menor medida, en las versiones 1.2 y 1.3.

1.4.0, 1.4.1 y 1.4.2 mostraron todos la pérdida de memoria grave.

1.2.3, 1.2.6, 1.3.0, 1.3.1 y 1.3.2 mostraron una fuga mucho más pequeña (aproximadamente 100 KB después de 10 minutos).

También probé una versión de mi programa que llama a Ajax de una manera más tradicional:

<html> <head> <script language="javascript" type="text/javascript"> function getHTTPObject() { var xmlhttp; /*@cc_on @if (@_jscript_version >= 5) try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (E) { xmlhttp = false; } } @else xmlhttp = false; @end @*/ if (!xmlhttp && typeof XMLHttpRequest != ''undefined'') { try { xmlhttp = new XMLHttpRequest(); if (xmlhttp.overrideMimeType) { xmlhttp.overrideMimeType("text/xml"); } } catch (e) { xmlhttp = false; } } return xmlhttp; } var ajaxObject = getHTTPObject(); setTimeout(testJunk,1000); function testJunk() { ajaxObject.open(''POST'', ''http://XXXXXXXXXXXXXXX/delme2'', true); ajaxObject.onreadystatechange = handleAjaxResponse; ajaxObject.send(null); } function handleAjaxResponse() { if (ajaxObject.readyState==4) { setTimeout(testJunk,1000); } } </script> </head> <body> <div id="test">Why is memory usage going up?</div> </body> </html>

Esto se deshizo de la fuga por completo.

Así que parece que tendré que repetir mi Ajax repetición de las viejas y feas maneras hasta que la gente de jQuery resuelva este problema.


Encontré el mismo problema y me quedé perplejo toda la mañana ... hasta hace unos momentos. El problema es una referencia circular que se crea cuando se configura el controlador onreadystatechange , que IE no es lo suficientemente inteligente como para romperlo. La solución, por lo tanto, es romperlo explícitamente. Sin embargo, obviamente no puedes hacerlo desde el mismo controlador (¡aunque sería conveniente si pudieras!).

La declaración de magia:

delete request[''onreadystatechange''];

onreadystatechange mantener un registro de cada objeto XMLHttpRequest para el que haya configurado onreadystatechange . Luego, en algún momento después de que readyState vaya a 4, haga su magia en el objeto. Si ya está realizando un sondeo AJAX repetido, el lugar lógico para verificar las solicitudes de limpieza estaría en el mismo ciclo de sondeo. RequestTracker objeto RequestTracker simple para administrar mis solicitudes.

Esto funcionó para mí; Verifiqué que resolvió la fuga. Aquí hay un enlace en particular que abrió el camino (publicaría más, pero no me lo permite):


He visto esto, y no creo que se trate de una pérdida de memoria. Es solo que la solicitud de Ajax se devuelve sin datos debido al almacenamiento en caché.

Agregue control de caché deliberado, como en:

$.ajax({ url: ''http://xxxxxxxxxxxxxx/test'', // The url returns an empty string dataType: ''html'', cache: false, success: function(data){} }); setTimeout(''testJunk()'',1000)

Es una de esas cosas donde las cosas caen por las grietas, es decir, hace algo específico con el almacenamiento en caché y XMLHttpRequest y jQuery no usa el caché desactivado de forma predeterminada.


Si está utilizando setinterval en javascript y no lo borra correctamente, el temporizador puede iniciarse varias veces, provocando una pila de llamadas.

intenta algo como

var myVar = setInterval(function() { clear() }, 5000); function clear() { clearInterval(myVar); GetData("ServiceLibrary","GetCalls",sdata,Complete); };


Un problema con su código es que si su solicitud de ajax comienza a tardar un poco, comenzará a inundar el navegador y el servidor con la solicitud de ajax, realmente debe esperar hasta que el navegador reciba una respuesta del servidor antes de iniciar la siguiente.

function testJunk() { $.ajax({ url: ''http://xxxxxxxxxxxxxx/test'', // The url returns an empty string dataType: ''html'', complete: function(data){ setTimeout(testJunk,1000); } }); } testJunk();


eval() consumirá memoria de forma segura (eval sucede cuando se pasa una cadena a setTimeout para evaluar), no la use en las pruebas:

setTimeout(''testJunk()'',1000);

debiera ser:

setTimeout(testJunk, 1000);

También un mejor uso en general sería setInterval() para una operación repetida que desee, intente esto:

setInterval(testJunk, 1000);