Cuando hablamos de Memory Leak (Fuga de memoria, no me gusta nada como suena), nos referimos a los problemas que un programa tiene para gestionar la memoria. En este caso, Internet Explorer 6 es un experto y siempre lo ha demostrado con famoso cuelgues y pantallazos azules que tan felices nos hacía. 😀
Uno de los mayores problemas con los que nos encontramos es que al crear objetos DOM, Internet Explorer 6 consume una memoria que al eliminar el elemento no termina de liberar. Douglas Crockford hace unos años comentaba este problema y nos ponía un ejemplo para ver el resultado en nuestras propias carnes.
Veamos un ejemplo que nos provoca este problema con el consumo de memoria:
/*global setTimeout */ (function (limit, delay) { var queue = new Array(10); var n = 0; function makeSpan(n) { var s = document.createElement('span'); document.body.appendChild(s); var t = document.createTextNode(' ' + n); s.appendChild(t); s.onclick = function (e) { s.style.backgroundColor = 'red'; alert(n); }; return s; } function process(n) { queue.push(makeSpan(n)); var s = queue.shift(); if (s) { s.parentNode.removeChild(s); } } function loop() { if (n < limit) { process(n); n += 1; setTimeout(loop, delay); } } loop(); })(10000, 10);
Como podemos ver si destripamos el código anterior, vemos como beneramos 10000 elementos <span />
y posteriormente los borramos. Si usamos la lógica al ejecutar este código, el consumo de memoria (Podemos verlo en Windows en Administrador de tareas de Windows > Uso de PF) se dispararía y despues volvería a su normalidad al eliminar los elementos, en Internet Explorer esto no ocurre así, cuando lanzamos el script este usa la memoria en crear los elementos, pero despues esta no se libera. Ahí el problema.
¿Como solucionarlo?
Veamos la función que devuelve el objeto que es la que ocasiona el problema.
function createButton() {
var obj = document.createElement("button");
obj.innerHTML = "click me";
obj.onclick = function() {
//handle onclick
}
obj.onmouseover = function() {
//handle onmouseover
}
return obj;//return a object which has memory leak problem in IE6
}
var dButton = document.getElementsById("d1").appendChild(createButton());
//skipped....
En este punto estamos devolviendo la dirección de memoria en la que se encuentra el objeto que acabamos de crear, en Internet Explorer esta porción de memoria nunca termina de liberarse al eliminar el objeto.
function createButton() {
var obj = document.createElement("button");
obj.innerHTML = "click me";
obj.onclick = function() {
//handle onclick
}
obj.onmouseover = function() {
//handle onmouseover
}
//this helps to fix the memory leak issue
try {
return obj;
} finally {
obj = null;
}
}
var dButton = document.getElementsById("d1").appendChild(createButton());
//skipped....
Gracias a try{}
podemos lanzar finally{}
que se ejecutará siempre despues de la ejecución, incluso despues del return de nuestras funciones, de esta forma vaciamos la porción de memoria y evitamos que posteriormente se quede inutilizada. Por otro lado, al estar devolviendo el objeto mediante el return, lo tenemos disponible como parámetro de la función padre que llame a esta.
3 comentarios, 1 referencias
+
#