2011/03/09

Optimización de javascript (IV). Técnicas de agilización de UI en tiempo de ejecución

La ejecución de funciones en javascript bloquean el refresco de la interfaz, de modo que mientras se están ejecutando no se actualiza la interfaz. Si un script se ejecuta durante demasiado tiempo, el navegador dará indicaciones de que no está respondiendo. El objetivo es mantener todas las ejecuciones de funciones javascript por debajo de los 50ms.

Para evitar que un proceso pesado bloquee la UI, están las siguientes técnicas. La función de referencia es la siguiente
function processArray(items, process, callback) {
        for (var i, len = items.length; i < len; i++) {
                process(items[i]);
        }
        callback();
}
Técnica de timers
Los timers permiten la ejecución de una función, añadiéndola a la cola de la UI para que se lance cuando hayan pasado x milisegundos.
setTimeout( function() {  ...código... }, 500); // Ejecuta la función después de 500ms
La función anterior quedaría como
function timedProcessArray(items, process, callback) {
        var todo = items.concat(); // Crea un clon de la lista de elementos original
        setTimeout(function() {
                var start = +new Date();
                do {
                        process(todo.shift());
                } while(todo.length > 0 && (+new Date() - start < 50));
                if(todo.length > 0) {
                        setTimeout(arguments.callee, 25)
                } else {
                        callback(items);
                }
        }, 25);
}
Técnica de web workers
Los web workers son scripts .js que se ejecutan de forma asíncrona en segundo plano respecto a la página que los invoca. Por lo tanto, al no ejecutarse en el proceso de la UI, no bloquean la actualización de la UI.
Están soportados por todos los navegadores menos el Internet explorer desde versiones muy antiguas.
Tienen una API serializada por datos, que se serializan cuando se les pasa al worker o son devueltos por él.
Los workers NO tienen acceso ni al DOM ni al BOM ya que se ejecutan en un entorno completamente separado.
// En la página principal
var worker = new Worker(“proceso.js”);
worker.onmessage = function(event) { useData(event.data); };
worker.postMessage(valores);
// En el worker (proceso.js)
self.onmessage = function(event) {
        var items = event.data;
        for(var i = 0, len = items.length; i < len; i++) {
                process(items[i]);
        }
        self.postMessage(items);
}

No hay comentarios:

Publicar un comentario