Web Workers es una API de JavaScript que permite ejecutar scripts en un hilo separado del principal. Puede ser útil cuando no quieres tener ningún obstáculo en la ejecución de los scripts principales, debido a los scripts de fondo.
Web Workers API es compatible con casi todos los navegadores; para obtener información más detallada, echa un vistazo a los documentos de CanIUse. Antes de entrar en el código, veamos un par de escenarios en los que es posible que desees utilizar esta API para que puedas hacerte una idea de lo que queremos decir con los scripts de fondo.
Casos de uso
Digamos que hay una secuencia de comandos que recupera y procesa un archivo. Si el archivo es considerablemente grande, tardará mucho tiempo en procesarse. Lo cual podría bloquear la ejecución de otros scripts que se invoquen posteriormente.
Sin embargo, si el procesamiento del archivo se mueve a un hilo de fondo, conocido como hilo de trabajo, otros eventos no se verán bloqueados hasta que el anterior termine.
El script ejecutado en un subproceso de trabajo en segundo plano se conoce como worker script o simplemente worker.
En otro ejemplo, imagina que hay un formulario grande, organizado en pestañas. Y que está escrito de manera que la actualización de controles en una pestaña afecta a algunos de los controles en otras.
Si la actualización de las pestañas lleva algún tiempo, el usuario no puede usar continuamente la pestaña actual sin que sus eventos se pongan en espera. Esto podría congelar la UI, para consternación del usuario.
Como el usuario no verá las otras pestañas mientras completa la actual, puede actualizar los controles de las otras pestañas en una secuencia de fondo. De esta forma, el usuario puede continuar usando la pestaña actual que está completando, sin que el proceso de actualización de controles en las otras pestañas bloquee ninguno de sus scripts.
Del mismo modo, si encuentras un escenario en el que una secuencia de comandos puede impedir que un usuario use la interfaz de usuario hasta que finalice su ejecución, puedes considerar moverla a una cadena de trabajo, para que pueda ejecutarse en segundo plano.
Ámbitos y tipos de Workers
Web Workers API es probablemente una de las API más simples. Tiene métodos bastante sencillos para crear subprocesos de trabajo y comunicarse con ellos desde el script principal.
El alcance global de un hilo de trabajo está en un contexto diferente del hilo principal. No puedes acceder a los métodos y propiedades de un objeto window como alert() dentro de un hilo de trabajo. Tampoco puedes cambiar el DOM directamente desde un hilo de trabajo.
Sin embargo, puedes usar muchas API incluidas en window, por ejemplo, Promise y Fetch en tu hilo de trabajo (consulta la lista completa).
También puedes tener subprocesos de trabajo anidados: subprocesos de trabajo creados a partir de otro subproceso de trabajo. Un worker creado por otro se llama subworker.
También hay muchos tipos de worker. Los dos principales son worker dedicados y worker compartidos.
Los worker dedicados pertenecen al mismo contexto de navegación al que pertenece su hilo principal. Los worker compartidos, sin embargo, están presentes en un contexto de navegación diferente (por ejemplo en un iframe) del script principal. En ambos casos, el guion principal y los worker deben estar en el mismo dominio.
El ejemplo en este tutorial será sobre el worker dedicado, que es el tipo más común.
Métodos API
Consulta el diagrama a continuación para obtener una descripción general rápida de todos los métodos principales que constituyen la API de Web Workers.
El constructor Worker() crea un hilo de trabajo dedicado y devuelve su objeto de referencia. Luego, usamos este objeto para comunicarnos con ese worker específico.
El método postMessage() se usa en las secuencias de comandos principal y de worker para enviar datos entre sí. Los datos enviados se reciben en el otro lado por el controlador de eventos onmessage.
El método terminate() termina un hilo del worker desde el script principal. Esta finalización es inmediata: cualquier ejecución actual de scripts y scripts pendientes se cancelarán. El método close() hace lo mismo, pero es llamado por el hilo del worker y se cierra.
Código de ejemplo
Ahora, veamos un código de muestra. La página index.html contiene la secuencia de comandos principal dentro de una etiqueta <script>, mientras que la secuencia de comandos del worker se encuentra en un archivo JavaScript llamado worker.js.
index.html |
|
|
<button>Click me</button> |
Comenzamos con la creación del hilo del worker desde el script principal.
index.html |
|
|
w = new Worker('worker.js'); |
El constructor Worker() toma la URL del archivo worker como su argumento.
A continuación, agregamos un controlador de eventos para el evento onmessage de la instancia de trabajo recién creada para recibir datos del mismo. La propiedad data del evento e contendrá los datos recibidos.
index.html |
|
|
w = new Worker('worker.js'); |
Ahora, utilizamos postMessage() para enviar algunos datos al hilo de worker con el clic de un botón. El método postMessage() puede tomar dos argumentos. El primero puede ser de cualquier tipo (cadena, matriz ...). Son los datos que se enviarán al hilo del worker (o al guion principal cuando el método está presente en el hilo del worker).
El segundo parámetro opcional es una matriz de objetos que pueden ser utilizados por los hilos del worker (pero no por el script principal, o viceversa). Este tipo de objetos se llaman objetos Transferable.
index.html |
|
|
document.querySelector('button').onclick = ()=>{ |
Solo estoy enviando un valor de cadena al hilo del worker.
En el hilo del worker, necesitamos agregar un controlador onmessage de eventos que recibirá los datos enviados por el script principal al hacer clic en el botón. Dentro del controlador, concatenamos la cadena recibida con otra y enviamos el resultado nuevamente al script principal.
worker.js |
|
|
console.info('worker created'); |
A diferencia del guión principal donde tuvimos que usar el objeto w de referencia para referirnos al hilo del worker específico en el cual el guión usa los métodos onmessage y postMessage, no hay necesidad de un objeto de referencia en el hilo del trabajador para apuntar al hilo principal.
El código funciona de la siguiente manera. Cuando se carga el navegador index.html, la consola mostrará el mensaje "worker created" tan pronto como se ejecute el constructor worker() en el hilo principal, creando un nuevo worker.
Cuando haces clic en el botón de la página, recibirá el mensaje "Received from worker: Hi john" en la consola, que es la cadena que se concatenó en el hilo del worker con los datos que se le enviaron, y luego se envió al guion principal.
Comentarios