HTML5: trabajadores web
JavaScript se diseñó para ejecutarse en un entorno de un solo subproceso, lo que significa que no se pueden ejecutar varios scripts al mismo tiempo. Considere una situación en la que necesita manejar eventos de IU, consultar y procesar grandes cantidades de datos de API y manipular el DOM.
JavaScript colgará su navegador en situaciones en las que la utilización de la CPU sea alta. Tomemos un ejemplo simple en el que JavaScript pasa por un gran bucle:
<!DOCTYPE HTML>
<html>
<head>
<title>Big for loop</title>
<script>
function bigLoop() {
for (var i = 0; i <= 10000; i += 1) {
var j = i;
}
alert("Completed " + j + "iterations" );
}
function sayHello(){
alert("Hello sir...." );
}
</script>
</head>
<body>
<input type = "button" onclick = "bigLoop();" value = "Big Loop" />
<input type = "button" onclick = "sayHello();" value = "Say Hello" />
</body>
</html>
Producirá el siguiente resultado:
Cuando haces clic en el botón Big Loop, se muestra el siguiente resultado en Firefox:
¿Qué son los Web Workers?
La situación explicada anteriormente se puede manejar usando Web Workers que realizará todas las tareas computacionalmente costosas sin interrumpir la interfaz de usuario y, por lo general, se ejecutará en subprocesos separados.
Los Web Workers permiten scripts de larga duración que no son interrumpidos por scripts que responden a clics u otras interacciones del usuario, y permiten que se ejecuten tareas largas sin ceder para mantener la página receptiva.
Los Web Workers son scripts en segundo plano y son relativamente pesados, y no están diseñados para usarse en grandes cantidades. Por ejemplo, no sería apropiado lanzar un trabajador por cada píxel de una imagen de cuatro megapíxeles.
Cuando un script se ejecuta dentro de un Web Worker, no puede acceder al objeto de ventana de la página web (window.document), lo que significa que los Web Workers no tienen acceso directo a la página web y la API DOM. Aunque los Web Workers no pueden bloquear la interfaz de usuario del navegador, aún pueden consumir ciclos de CPU y hacer que el sistema sea menos receptivo.
¿Cómo funcionan los Web Workers?
Los Web Workers se inicializan con la URL de un archivo JavaScript, que contiene el código que ejecutará el trabajador. Este código establece detectores de eventos y se comunica con el script que lo generó desde la página principal. A continuación se muestra la sintaxis simple:
var worker = new Worker('bigLoop.js');
Si existe el archivo javascript especificado, el navegador generará un nuevo hilo de trabajo, que se descarga de forma asincrónica. Si la ruta a su trabajador devuelve un error 404, el trabajador fallará silenciosamente.
Si su aplicación tiene varios archivos JavaScript compatibles, puede importarlos importScripts() método que toma el (los) nombre (s) de archivo como argumento separado por coma de la siguiente manera:
importScripts("helper.js", "anotherHelper.js");
Una vez que se genera el Web Worker, la comunicación entre el Web Worker y su página principal se realiza mediante el postMessage()método. Dependiendo de su navegador / versión, postMessage () puede aceptar una cadena o un objeto JSON como su único argumento.
Se accede al mensaje pasado por Web Worker usando onmessageevento en la página principal. Ahora escribamos nuestro ejemplo de bigLoop usando Web Worker. A continuación se muestra la página principal (hello.htm) que generará un trabajador web para ejecutar el bucle y devolver el valor final de la variablej -
<!DOCTYPE HTML>
<html>
<head>
<title>Big for loop</title>
<script>
var worker = new Worker('bigLoop.js');
worker.onmessage = function (event) {
alert("Completed " + event.data + "iterations" );
};
function sayHello() {
alert("Hello sir...." );
}
</script>
</head>
<body>
<input type = "button" onclick = "sayHello();" value = "Say Hello"/>
</body>
</html>
A continuación se muestra el contenido del archivo bigLoop.js. Esto hace uso depostMessage() API para pasar la comunicación a la página principal -
for (var i = 0; i <= 1000000000; i += 1) {
var j = i;
}
postMessage(j);
Esto producirá el siguiente resultado:
Detener a los trabajadores web
Los Web Workers no se detienen solos, pero la página que los inició puede detenerlos llamando terminate() método.
worker.terminate();
Un Web Worker despedido ya no responderá a los mensajes ni realizará cálculos adicionales. No puede reiniciar un trabajador; en su lugar, puede crear un nuevo trabajador con la misma URL.
Manejo de errores
A continuación se muestra un ejemplo de una función de manejo de errores en un archivo JavaScript de Web Worker que registra errores en la consola. Con el código de manejo de errores, el ejemplo anterior se convertiría en el siguiente:
<!DOCTYPE HTML>
<html>
<head>
<title>Big for loop</title>
<script>
var worker = new Worker('bigLoop.js');
worker.onmessage = function (event) {
alert("Completed " + event.data + "iterations" );
};
worker.onerror = function (event) {
console.log(event.message, event);
};
function sayHello() {
alert("Hello sir...." );
}
</script>
</head>
<body>
<input type = "button" onclick = "sayHello();" value = "Say Hello"/>
</body>
</html>
Comprobación de compatibilidad con el navegador
A continuación se muestra la sintaxis para detectar la compatibilidad con una función de Web Worker disponible en un navegador:
<!DOCTYPE HTML>
<html>
<head>
<title>Big for loop</title>
<script src = "/js/modernizr-1.5.min.js"></script>
<script>
function myFunction() {
if (Modernizr.webworkers) {
alert("Congratulation!! you have web workers support." );
} else {
alert("Sorry!! you do not have web workers support." );
}
}
</script>
</head>
<body>
<button onclick = "myFunction()">Click me</button>
</body>
</html>
Esto producirá el siguiente resultado: