Trabajadores web

Aprenda a ejecutar código JavaScript en segundo plano con Web Workers

Introducción

JavaScript es de un solo hilo. Nada puede funcionar en paralelo al mismo tiempo.

Esto es genial porque no tenemos que preocuparnos por todo un conjunto de problemas que sucederían con la programación concurrente.

Con esta limitación, el código JavaScript se ve obligado a ser eficiente desde el principio, de lo contrario el usuario tendría una mala experiencia. Las operaciones costosas deben ser asincrónicas para evitar bloquear el hilo.

A medida que crecieron las necesidades de las aplicaciones JavaScript, esto comenzó a convertirse en un problema en algunos escenarios.

Los Web Workers introducen la posibilidad de ejecución paralela dentro del navegador.

Tienen bastantes limitaciones:

  • sin acceso a laDOM: el objeto Ventana y el objeto Documento
  • Pueden comunicarse con el programa JavaScript principal mediante mensajería.
  • deben cargarse desde el mismo origen (dominio, puerto y protocolo)
  • no funcionan si publica la página utilizando el protocolo de archivo (file://)

El alcance global de un Web Worker, en lugar de Window que está en el hilo principal, es unWorkerGlobalScopeobjeto.

Soporte de navegador para trabajadores web

¡Bastante bueno!

Browser support for web workers

Puede comprobar el soporte de Web Workers utilizando

if (typeof Worker !== 'undefined') {
}

Crear un trabajador web

Usted crea un Web Worker inicializando un objeto Worker, cargando un archivo JavaScript desde el mismo origen:

const worker = new Worker('worker.js')

Comunicación con un trabajador web

Hay dos formas principales de comunicarse con un Web Worker:

Usando postMessage en el objeto Web Worker

Puedes enviar mensajes usandopostMessagesobre elWorkerobjeto.

Importante: un mensaje se transfiere, no se comparte.

main.js

const worker = new Worker('worker.js')
worker.postMessage('hello')

worker.js

onmessage = event => {
  console.log(event.data)
}

onerror = event => { console.error(event.message) }

Enviar mensajes de vuelta

Un trabajador puede enviar mensajes a la función que lo creó. usando su globalpostMessage()función:

worker.js

onmessage = event => {
  console.log(event.data)
  postMessage('hey')
}

onerror = event => { console.error(event.message) }

main.js

const worker = new Worker('worker.js')
worker.postMessage('hello')

worker.onmessage = event => { console.log(event.data) }

Oyentes de eventos múltiples

Si desea configurar varios oyentes para elmessageevento, en lugar de usaronmessagecrear un detector de eventos (se aplica a laerrorevento también):

worker.js

addEventListener('message', event => {
  console.log(event.data)
  postMessage('hey')
}, false)

addEventListener(‘message’, event => { console.log(I'm curious and I'm listening too) }, false)

addEventListener(‘error’, event => { console.log(event.message) }, false)

main.js

const worker = new Worker('worker.js')
worker.postMessage('hello')

worker.addEventListener(‘message’, event => { console.log(event.data) }, false)

Uso de la API de mensajería de canal

En lugar de utilizar la API postMessage incorporada que ofrecen los Web Workers, podemos optar por utilizar la API de propósito más generalAPI de mensajería de canalpara comunicarse con ellos.

main.js

const worker = new Worker('worker.js')
const messageChannel = new MessageChannel()
messageChannel.port1.addEventListener('message', event => {
  console.log(event.data)
})
worker.postMessage(data, [messageChannel.port2])

worker.js

addEventListener('message', event => {
  console.log(event.data)
})

Un Web Worker puede enviar mensajes enviando un mensaje amessageChannel.port2, como esto:

addEventListener('message', event => {
  event.ports[0].postMessage(data)
})

Ciclo de vida del trabajador web

Los Web Workers se inician y si no permanecen en modo de escucha para recibir mensajesworker.onmessageo al agregar un detector de eventos, se cerrarán tan pronto como su código se ejecute hasta su finalización.

Un Web Worker puede detenerse usando suterminate()método desde el hilo principal, y dentro del propio trabajador usando el método globalclose():

main.js

const worker = new Worker('worker.js')
worker.postMessage('hello')
worker.terminate()

worker.js

worker.onmessage = event => {
  console.log(event.data)
  close()
}

worker.onerror = event => { console.error(event.message) }

Carga de bibliotecas en un Web Worker

Los trabajadores web pueden utilizarimportScripts()función global definida en su ámbito global:

importScripts('../utils/file.js', './something.js')

API disponibles en Web Workers

Como se dijo antes, un Web Worker no puede acceder al DOM, por lo que no puede interactuar con elwindowydocumentobjetos. tambiénparentno está disponible.

Sin embargo, puede utilizar muchas otras API, que incluyen:


Más tutoriales de navegador: