Video Summary and Transcription
Esta Charla compara los web workers, incluyendo los workers dedicados, los workers compartidos y los service workers. Los web workers proporcionan capacidades de multithreading y utilizan memoria compartida para un mayor rendimiento. Los workers dedicados tienen un padre y pueden ejecutarse en un hilo separado. Los workers compartidos pueden tener múltiples padres y son útiles para la comunicación entre diferentes ventanas. Los service workers pueden interceptar y proxy las solicitudes realizadas desde una página web y son útiles para almacenar en caché los activos de red y construir aplicaciones web progresivas.
1. Introducción a los Web Workers
Hola, soy Thomas Hunter y esta charla es una comparación de los web workers. Hoy vamos a hablar de los dedicated workers, shared workers y service workers. JavaScript es de un solo hilo, pero los web workers proporcionan capacidades de multihilo. Los web workers utilizan memoria compartida para un mayor rendimiento y multihilo. Cada entorno de JavaScript está aislado, con sus propias variables y globales. Los web workers no pueden acceder al DOM, pero se puede utilizar memoria compartida para acceder a los datos.
Hola, soy Thomas Hunter y esta charla es una comparación de los web workers. El contenido de esta charla está adaptado de un libro que publiqué recientemente, JavaScript Multihilo. Si quieres más información sobre el libro, no dudes en seguir la URL de bitly que se encuentra en la parte inferior de la pantalla.
Muy bien. Así que hoy vamos a hablar de tres temas diferentes. El primero son los dedicated workers. El segundo son los shared workers. Y el tercero son los service workers. Cada uno de estos workers es un tipo de web worker. Pero primero, voy a hablar de algunos conceptos básicos. Así que, primero, el concepto de multihilo en JavaScript. Una cosa a tener en cuenta es que es la naturaleza de JavaScript y su ecosistema ser de un solo hilo. Durante mucho tiempo, no existían realmente capacidades de multihilo en JavaScript. Podías hacer algo parecido utilizando el envío de mensajes básico, utilizando iframes. Pero no era exactamente la solución más limpia. Sin embargo, ahora tenemos los web workers disponibles. Y con eso viene una característica llamada memoria compartida, que permite un mayor rendimiento y multihilo que simplemente utilizar el envío de mensajes. Esta presentación se va a centrar en el uso de estos web workers con fines de multihilo ya que está relacionado con el libro. Muy bien. Otro concepto básico es, bueno, ¿qué es un entorno de JavaScript? Bueno, un entorno de JavaScript es una colección aislada de variables, globales, cosas como, ya sabes, el objeto capital O van a ser diferentes en estos entornos separados, las cadenas de prototipos, ya sabes, a qué objetos terminan apuntando son diferentes en estos diferentes entornos. Cada entorno adicional va a tener un cierto costo adicional para iniciarse y en Node es más fácil de medir. En mis experimentos se consumían alrededor de seis megabytes de memoria por cada nueva instancia de hilo de trabajo. En un navegador vas a tener un poco más de costo adicional. Los web workers van a tener un cierto costo adicional de memoria y luego si tienes páginas adicionales habrá aún más costo adicional ya que hay diferentes documentos y rectángulos que deben renderizarse. Estas instancias de objetos que se crean en estos diferentes entornos nunca pueden ser verdaderamente compartidas entre entornos. Sin embargo, puedes serializar estos objetos, puedes clonarlos o puedes representarlos como JSON y luego pasarlos entre los diferentes entornos. Sin embargo, si mutas uno en un lugar, no lo estás mutando en el otro. Ninguno de los web workers que vamos a ver hoy tiene acceso al DOM. Por ejemplo, el objeto document global no está disponible dentro de los web workers. Si utilizas el shared array buffer, si pasas uno de esos entre estos diferentes entornos, se compartirá un puntero a los mismos datos binarios en memoria y así es como podemos tener datos de memoria compartida.
2. Dedicated Workers
Un dedicated worker es el tipo más simple de web worker. Tiene un padre y puede cargar otros dedicated workers. Cada worker proporciona un nuevo entorno de JavaScript y puede ejecutarse en un hilo separado. Para trabajar con un dedicated worker, instanciamos una instancia de worker, adjuntamos un controlador de mensajes y enviamos mensajes utilizando postMessage. El archivo worker.js maneja los mensajes recibidos del padre y puede realizar cálculos intensivos en CPU antes de enviar un mensaje de vuelta.
acceso. Y gran parte de esta explicación es una simplificación de algunas complejidades internas en relación con el contexto y los reinos y cómo funciona realmente la VM de JavaScript. Muy bien. Ahora, veamos los dedicated workers. ¿Qué es un dedicated worker? Bueno, un dedicated worker es el tipo más simple de los web workers que vamos a ver. Cada uno de estos dedicated workers puede tener exactamente un padre. De hecho, puedes cargarlos jerárquicamente si quieres donde los dedicated workers también pueden cargar otros dedicated workers. Y cada uno de estos workers nos proporciona un nuevo entorno de JavaScript. Cada uno también puede ejecutarse en un hilo separado.
Ahora, veamos un ejemplo de código. Así es como trabajaríamos con un dedicated worker desde el contexto de la página web. Tal vez esto se encuentre en un archivo index.html. Tal vez se encuentre dentro de main.js cargado por un archivo HTML. Pero en cualquier caso, esto se ejecuta en el hilo principal que dibuja la ventana. Y así, los navegadores modernos nos proporcionan un objeto global con mayúscula W, worker. Podemos instanciar eso para crear una instancia de un worker. El argumento de esto es la ruta a un archivo que queremos utilizar como el worker. Una vez que obtenemos el worker, podemos adjuntar un controlador de mensajes en él. Aquí estoy asignando this.onmessage, que es una función de devolución de llamada. Cuando se llama a esta función, imprimirá el mensaje del worker y luego imprimirá los datos que se le pasaron. Este código se ejecutará dentro del hilo padre cuando el hilo del dedicated worker le haya pasado un mensaje. Y a la inversa, si queremos pasar un mensaje al worker, llamamos a worker.postMessage donde pasamos un argumento. Estoy pasando una cadena, pero también podríamos pasar otros valores simples o objetos básicos con algunas advertencias. Y finalmente, al final del archivo, simplemente estamos registrando que se ha ejecutado el final del archivo main.js. Ahora veamos el dedicated worker dentro del worker. Este es nuestro archivo worker.js que se mencionó en la diapositiva anterior. En este archivo, lo primero que hacemos es registrar que estamos dentro del worker. Luego asignamos un controlador global onmessage, que acepta el mensaje que se le pasó desde el padre. Y dentro de este controlador, registramos un mensaje que hemos recibido un mensaje de main, registramos los datos que se nos pasaron. En este punto de la aplicación, este podría ser un buen lugar para realizar un cálculo intensivo en CPU. Y finalmente, podemos llamar a postMessageGlobal para enviar un mensaje de vuelta al padre.
3. Ejecución de código y Workers dedicados/compartidos
Vamos a ejecutar el código y ver la salida. Vemos el mensaje 'Hola desde Main', que se pasa al hijo. El mensaje luego es recibido y procesado por el worker. El worker imprime 'hola desde el worker' y 'mensaje de Main al worker'. También se imprime el mensaje final del worker. Los workers dedicados proporcionan acceso a un hilo adicional, lo que permite descargar trabajos intensivos en CPU y evitar ralentizaciones. Sin embargo, si el padre muere, el worker dedicado también morirá. Los workers compartidos pueden tener múltiples padres y son útiles para comunicarse entre diferentes ventanas, siempre y cuando sigan las mismas reglas de origen.
Entonces, vamos a ejecutar el código y ver la salida. Aquí ya lo he ejecutado por nosotros. Lo primero que vemos es el mensaje 'Hola desde Main'. Y aunque pasamos el mensaje al hijo, terminamos registrando el mensaje 'Hola desde el final de Main'. Pasa un tiempo no determinista antes de que el mensaje sea recibido y procesado por el worker. Dentro de él, imprimimos 'hola desde el worker' y luego imprimimos 'mensaje de Main al worker'. Finalmente, se imprime el mensaje que se devolvió al hilo padre. Desde el worker, mensaje del worker, ese es el mensaje final allí. Entonces, ¿por qué querrías usar un worker dedicado? Bueno, la razón más importante en mi opinión es que proporciona acceso a un hilo adicional. Es una excelente manera de descargar trabajos intensivos en CPU o cosas que podrían ralentizar un navegador web. Cosas que podrían causar tartamudeo al desplazarse, puedes descargarlas en este hilo adicional. Y así, pasas el mensaje al hilo y luego el hilo principal puede realizar otro trabajo. Y una vez que recibe un mensaje de vuelta de ese worker dedicado, puede manejar ese valor y luego continuar con lo que está haciendo. Una cosa a tener en cuenta es que un worker dedicado, cada vez que su único padre muere, ese worker dedicado también morirá.
A continuación, vamos a ver los workers compartidos. ¿Qué es un worker compartido? Bueno, un worker compartido es bastante similar, pero puede tener múltiples padres. Es útil para comunicarse entre diferentes ventanas. Hay una advertencia de que estas ventanas deben estar en el mismo origen. Por ejemplo, no puedes tener la página web de Google comunicándose con la página web de Microsoft. Deben seguir las mismas reglas de origen. Entonces, nuevamente, veamos un código de ejemplo. Primero, vamos a ver el código que podría ejecutarse en una página HTML. Y así, podemos fingir que tenemos dos páginas HTML diferentes. Ambas tienen un script. Una es la página HTML roja y la otra es la página HTML azul. Dentro de estos archivos, tenemos una etiqueta de script que instancia un worker compartido. El worker compartido está disponible nuevamente en navegadores modernos con una pequeña advertencia que cubriré al final. Al igual que con los otros workers, instanciamos el worker compartido y pasamos un argumento, que es la ruta al archivo que se utilizará como el archivo del worker. Sin embargo, la API para interactuar con él es ligeramente diferente, donde en lugar de asignar directamente una propiedad onMessage al worker, la asignamos a un puerto. Y así, esa propiedad del puerto
4. Using Shared Workers
La interfaz del worker compartido es similar al worker dedicado, con una devolución de llamada que toma un argumento de evento. Pasamos un mensaje al worker compartido usando worker.port.postMessage. En el archivo JavaScript del worker compartido, generamos un ID, imprimimos un mensaje de registro, creamos un conjunto llamado ports para almacenar los puertos pasados y manejamos las conexiones usando el método onconnect. Extraemos el puerto de la conexión, lo agregamos al conjunto de puertos y registramos la conexión y el número de páginas conectadas. También asignamos un controlador onmessage al puerto para manejar los mensajes entrantes. Con los workers compartidos, podemos tener múltiples padres, por lo que iteramos sobre el conjunto de puertos y llamamos a postMessage en cada puerto para enviar un mensaje de vuelta. Ejecutemos este código en nuestra máquina.
representa un puerto de comunicación dentro del propio worker. Y así, la interfaz, por lo demás, esto es bastante similar al worker dedicado, donde es una devolución de llamada que toma un argumento de evento con una propiedad data que se pasa a ella. En este caso, solo estamos registrando un mensaje que dice que hemos recibido un evento. Y luego, más adelante, lo que queremos hacer es pasar un mensaje al worker compartido desde uno de los archivos HTML. Y para hacer eso, llamaríamos a worker.port.postMessage, pasando el mensaje que queremos enviar.
Bien. Aquí hay un código sobre cómo usar el worker compartido desde la perspectiva del worker. Este es nuestro archivo JavaScript del worker compartido. Ahora, hay un poco de complejidad aquí y trataré de explicarlo paso a paso. Pero realmente, el propósito de esto es simplemente mostrar cómo funciona el worker compartido. Lo primero que hago en el worker compartido es generar un ID. Ese número es solo un número aleatorio grande para mostrar que este código solo se ejecutará una vez. Y luego, lo siguiente que hacemos es imprimir un mensaje de registro que dice que estamos dentro del archivo shared.js y registramos ese ID nuevamente. A continuación, creamos una variable llamada ports. Y eso es un conjunto que contendrá los puertos que se le pasen a él. Después de eso, tenemos un método onconnect que se asigna a self. Y así, esto es una devolución de llamada que se llama cada vez que una página web diferente establece una conexión con el worker compartido. Entonces, si alguna vez has trabajado con websockets, este patrón de código podría resultarte un poco familiar. Lo primero que hacemos es extraer el puerto de la conexión y luego lo agregamos a nuestro conjunto de puertos. Y luego simplemente registramos que se ha establecido una conexión. Registramos el ID nuevamente y también el tamaño de los puertos, que nos dirá cuántas páginas están conectadas. Después de eso, asignamos un controlador onmessage al propio puerto, y eso indica que cuando este puerto reciba un mensaje. Entonces, cuando una de las páginas HTML envíe un mensaje a este worker compartido, queremos poder manejarlo aquí. Nuevamente, registraremos el mensaje, diremos que se recibió el mensaje, se pasó el ID en los datos. Ahora, anteriormente con el worker dedicado, cuando queríamos enviar un mensaje de vuelta al padre, era bastante sencillo. Había un solo puerto y simplemente enviábamos el mensaje a través de él. Sin embargo, con los workers compartidos, dado que podemos tener más de un padre, es por eso que estamos agregando cada uno de los puertos al conjunto de puertos, y luego los estamos iterando aquí y llamando al método postMessage en cada uno de ellos. Ahora, postMessage solo nos permite enviar un solo valor a través de él. Sin embargo, en este caso, estoy abusando un poco de un array para pasar el ID y los datos que se recibieron también. Y así que digamos que realmente ejecutamos este código en nuestra
5. Shared Worker Communication and Usage
Abrimos el archivo red.html y se ejecuta el archivo shared.js. Se genera un ID, se establece una conexión y el archivo red.html se conecta al worker compartido. Abrimos el archivo blue.html, se emite otra conexión y ahora el número de conexiones es dos. Pasamos un mensaje al worker compartido y este imprime el mensaje recibido y su ID. Los mensajes se envían a los archivos HTML que los llaman. No hay garantía sobre el orden de ejecución. Los workers compartidos son útiles para la comunicación entre páginas y para mantener ámbitos de variables. No son compatibles con Safari, pero funcionan en Chrome y Firefox. Si se necesita coordinación entre páginas, se puede utilizar el canal de difusión como alternativa. Un worker compartido se cierra cuando su último padre se cierra.
máquina. Así que tal vez lo primero que hagamos sea abrir el archivo red.html. Y entonces, lo que sucede, vamos a ver que se ejecuta el archivo shared.js. Y vemos que se generó un ID. Ese ID es 1, 2, 3, 4, 5, 6. Y luego vemos que se establece una conexión. Y el archivo red.html se conecta al worker compartido. Y nuevamente, imprimimos ese ID. Y el ID es el mismo.
Luego abrimos el otro archivo. Abrimos el archivo blue.html. En ese momento, vemos que se emite otra conexión. Y el ID se repite nuevamente. Y vemos que el número de conexiones ahora es dos. Y después de eso, ejecutamos el ejemplo de postMessage de dos diapositivas anteriores, donde pasamos el mensaje, hola, mundo, al worker compartido. Y cuando eso sucede, el worker compartido imprime que recibió un mensaje, imprime su ID nuevamente y el mensaje que recibió. Y luego envía esos mensajes a los archivos HTML que los llaman. Y cuando eso sucede, se llama a la línea de evento, se imprimen las dos últimas líneas de evento en la pantalla. Y esas se verán dentro de la consola del inspector en esas páginas específicas.
No hay una garantía en este caso sobre el orden en que se realizan los registros del archivo blue HTML. Esa es un poco la emoción divertida de la multihilo, que no siempre hay una garantía sobre el orden en que se ejecuta esto. Entonces, ¿por qué podrías usar un worker compartido? Bueno, tal vez necesites comunicarte entre páginas. Es bastante útil para mantener, como, un contexto con variables asociadas, y especialmente en casos en los que deseas que esos ámbitos de variables sobrevivan más allá de la vida de una página. Y así, tal vez algunas aplicaciones de una sola página más pesadas dependan de esto. Realmente queremos coordinar cosas entre diferentes páginas. Entonces, otro patrón es tal vez quieres crear un singleton, ya sabes, una única fuente de verdad, y quieres que se acceda a ella desde diferentes páginas. Una cosa a tener en cuenta es que, desafortunadamente, los workers compartidos no son compatibles con Safari. Creo que los admitieron en algún momento, pero luego, por consideraciones de security, terminaron eliminándolos. Sin embargo, funcionan en Chrome y Firefox. Si te encuentras necesitando un patrón para coordinar la comunicación entre diferentes páginas, puedes considerar utilizar el canal de difusión como alternativa, y eso también está disponible en navegadores modernos. Ahora, una cosa a tener en cuenta es que un worker compartido se cerrará cuando su último padre se cierre, por lo que si abrimos varias páginas, tal vez terminemos abriendo 10 de ellas, no será hasta que, luego, comiences a cerrar estas diferentes páginas y no será hasta que cierres la página final que el worker compartido terminará siendo eliminado también.
6. Service Workers and Intercepting Requests
Los service workers son los más complejos de los web workers. Pueden interceptar y hacer de proxy en las solicitudes realizadas desde una página web, incluyendo solicitudes fetch, solicitudes AJAX y activos cargados. Los service workers pueden técnicamente no tener padres y ejecutarse en segundo plano. Se pueden utilizar para compartir estado entre ventanas del mismo origen. Para crear un service worker, utilizamos el método navigator.serviceWorker.register con una ruta al archivo del worker y un objeto de configuración. La propiedad scope define el rango de URL que el worker puede controlar. Podemos manejar cambios de estado, como oncontrollerchange, y registrar mensajes cuando el service worker toma el control de la página. La función makeRequest obtiene datos de un archivo y los registra en la pantalla. El archivo del service worker, sw.js, es donde se implementa la lógica del service worker.
También puedes terminar manualmente estos web workers si así lo deseas. Muy bien, finalmente, echemos un vistazo a los service workers. ¿Qué es un service worker? Bueno, un service worker es el más complejo de los web workers. La característica más genial que admiten es la capacidad de interceptar o hacer de proxy en las solicitudes que se realizan a un servidor desde una página web. Esto incluye cosas como solicitudes fetch, solicitudes AJAX, pero también incluye cosas como imágenes que se cargan, activos que se cargan desde CSS, el archivo favicon. Muchas de esas cosas, básicamente todas, terminan pasando a través del service worker.
Algo interesante sobre el service worker es que técnicamente puede no tener padres y se ejecuta en segundo plano. Por lo tanto, necesitas una página para ejecutarse y terminar instalando el service worker. Pero una vez que esa página se cierra, el service worker técnicamente permanece instalado en el navegador. El comportamiento de cuándo aparece y desaparece, cuándo vive y muere, es un poco menos definido en el sentido de que no es algo en lo que necesariamente quieras depender. Por lo tanto, puedes usar los service workers para compartir estado entre ventanas del mismo origen también. Muy bien. Veamos otro ejemplo de código. En este caso, cuando vemos los service workers en la página web, nuevamente, en este caso, la interfaz para crear el worker es un poco diferente. Aquí estamos llamando a navigator.service Worker.register. Al igual que con los otros web workers, el primer argumento es una ruta al archivo que representa al worker. También hay un objeto de configuración adicional, y la propiedad de configuración más comúnmente utilizada es el ámbito (scope). Por lo tanto, el ámbito nos permite definir el rango de URL que el worker puede controlar. En este caso, estamos diciendo que todo lo que se carga y comienza con una barra diagonal está bajo control. Básicamente, estamos diciendo que todo en este dominio está bajo control. También obtenemos algunos cambios de estado diferentes a los que podemos acceder. En este caso, estamos manejando el evento oncontrollerchange, y simplemente vamos a registrar un mensaje en la pantalla. Por lo tanto, lo que dice es que, cuando la página actual, cuando un service worker toma el control de la página, lo que significa que en ese momento las solicitudes son interceptadas, vamos a registrar un mensaje que indique que ahora está funcionando. Entonces, la última función que tenemos aquí es makeRequest. Esto es solo con fines ilustrativos, y lo ejecutaremos en un momento. Pero lo que hace es hacer una solicitud fetch a un archivo en el servidor actual llamado data.json. Deserializa el resultado y luego lo registra en la pantalla. Muy bien, ahora veamos los service workers dentro del propio worker. Este es nuestro archivo sw.js. Esta es la primera mitad.
7. Service Worker Installation and Activation
Creamos una variable llamada contador y la establecemos en cero. El método on install registra un mensaje cuando el service worker se instala. El método on activate registra un mensaje cuando el service worker se activa. El service worker intercepta las solicitudes de las páginas abiertas actualmente después de que se actualizan. El controlador on fetch registra la URL recibida y verifica si termina en data.json. Si no es así, se realiza una solicitud HTTP normal. Si lo hace, se incrementa la variable contador y se crea una nueva respuesta con un objeto JSON que contiene el contador. El tipo de contenido se establece en text.JSON. Los registros muestran la instalación, activación y cambio de controlador del service worker, pero su orden no está garantizado.
Entonces, lo primero que estamos haciendo aquí es crear una variable llamada contador y la establecemos en cero. A continuación, asignamos un método on install en nuestro objeto self y eso nos dice cuándo se está instalando el service worker. En este caso, simplemente vamos a registrar un mensaje de que se ha realizado la instalación.
Después de eso, tenemos un on activate, y esto se llama cuando el service worker alcanza la etapa o estado de activación, ya que estos service workers actúan como una máquina de estados. Entonces, cuando esto sucede, simplemente vamos a registrar un mensaje de que el service worker está ahora activo, pero también vamos a hacer algo más interesante. Cuando un service worker se activa por primera vez, las páginas abiertas, las solicitudes que envían no se envían inmediatamente a través de este service worker. No es hasta que la página se actualiza que esas páginas quedan bajo el control del service worker. Entonces, lo que estamos haciendo aquí en la parte inferior, estamos llamando a event.waitUntil, que acepta una promesa, y la promesa es el resultado de la llamada self.clients.claim. Eso significa básicamente que las páginas que están abiertas actualmente, el service worker interceptará la solicitud. Muy bien. El archivo continúa y aquí está la segunda mitad. También tenemos este controlador on fetch. Este controlador on fetch se llama cada vez que el service worker recibe una solicitud de red de una de las páginas web. Entonces, dentro de este controlador, lo que estamos haciendo primero es registrar la URL que se recibió. A continuación, tenemos una declaración if, por lo que aquí verificamos si la URL que se recibió termina en data.json. Si no es así, entonces saltamos al final y volvemos esencialmente a una solicitud HTTP normal. Entonces, aquí tenemos este evento que responde con, y eso acepta una promesa que se resuelve en un valor que se le da al navegador como resultado de la solicitud. Y así, el valor que le estamos dando es la respuesta de fetch, que es una promesa, y luego el argumento que proporcionamos a fetch es la solicitud entrante, que es event.request. Entonces, básicamente, lo que esa línea está diciendo es simplemente realizar una solicitud normal y no hacer nada con ella. Sin embargo, si la URL terminó en data.JSON, ejecutamos el cuerpo de esa declaración if. Entonces, lo que hacemos allí es incrementar esa variable contador de antes, y luego simplemente llamamos a event.respondWith, puedes ignorar ese return void, pero simplemente llamamos a event.respondWith, donde pasamos una nueva respuesta que estamos creando desde cero. Y así, el cuerpo de esa respuesta es un objeto JSON que contiene nuestro contador en la variable. Y luego, solo con fines ilustrativos, establecemos las cabeceras, por lo que en este caso, establecemos el tipo de contenido en text.JSON. Y así, si ejecutamos este código, estos son los registros que veremos. Entonces, lo primero que vemos es que se ha instalado el service worker. A continuación, vemos que el service worker ha sido activado. Y luego, finalmente, vemos que ha ocurrido un cambio de controlador. Nuevamente, el orden de estos mensajes no es determinista, ya que el navegador, ya sabes, puede manejar un registro y almacenarlo en memoria. Bueno, imprimirá un registro desde otra ubicación.
8. Using Service Workers and Web Worker Comparison
A continuación, llamamos a make request desde la página web, lo que hará nuestra solicitud fetch al servidor. main.js recibe ese mensaje e imprime el resultado, que en este caso es el contador establecido en 1. Los service workers son útiles para almacenar en caché activos de red, realizar sincronización en segundo plano, admitir notificaciones push y crear aplicaciones web progresivas. Sin embargo, la vida útil de un service worker no está garantizada y se recomienda utilizar las API de caché para el almacenamiento persistente. Los workers dedicados, compartidos y de servicio proporcionan hilos adicionales para fines de multiprocesamiento y tienen características y casos de uso diferentes.
Entonces, el orden de estos primeros dos mensajes no está garantizado. A continuación, llamamos a make request desde la página web, lo que hará nuestra solicitud fetch al servidor. Entonces, eso sucede. Imprimimos que se realizó la solicitud fetch. Simplemente imprime la URL que se recibió y luego devuelve el objeto JavaScript a través de la solicitud de red. Y finalmente, main.js recibe ese mensaje e imprime el resultado, que en este caso es el contador establecido en 1. Y luego, si ejecutamos la función make request varias veces, cada una de esas solicitudes dará como resultado un contador diferente.
Entonces, ninguna de estas solicitudes se envía realmente a ese servidor que se ejecuta en localhost puerto 500, todas son manejadas por el service worker. Entonces, ¿por qué querrías usar un service worker? Bueno, es realmente útil para almacenar en caché activos de red si una aplicación está sin conexión. Puedes usarlo para realizar sincronización en segundo plano de contenido que se actualiza, y si actualizas contenido en el servidor, el service worker puede decidir cómo devolverlo al cliente. Si deseas admitir notificaciones push, eso también se hace en el service worker. Si eres como yo y te gusta crear aplicaciones web progresivas y quieres que esas aplicaciones se agreguen a la pantalla de inicio, tanto Android con Chrome como iOS con Safari utilizarán estos service workers, y es uno de los requisitos antes de poder agregar tu PWA a la pantalla de inicio. Una cosa a tener en cuenta es que un service worker puede morir cuando muere el último padre, pero sigue existiendo y no hay una garantía de cuánto tiempo permanecerán esos cierres en memoria. Entonces, si piensas en el ejemplo que mencioné con esa variable contador, en realidad es un poco un patrón incorrecto. Realmente no querrías crear un estado en memoria en un service worker donde esperarías que permanezca. Y si deseas hacer cosas que sean un poco más persistentes, por ejemplo, si deseas poner cosas en cachés. Hay todo tipo de API de caché disponibles dentro de los service workers para mantener esos datos en un estado más persistente. Entonces, si quisieras tomar una captura de pantalla de esta presentación, esta es probablemente la que debes hacer. Y así, aquí tenemos una comparación entre los diferentes tipos de workers web. Y así, a la izquierda, tengo la característica y luego cómo funciona para los workers dedicados, compartidos y de servicio. Y así, los tres de estos workers web, cada uno de ellos proporcionará un hilo adicional que se puede utilizar para fines de multiprocesamiento. Si tienes un servidor que no sirve contenido a través de HTTPS, pero solo puedes usar workers dedicados y compartidos, no puedes usar un service worker con él. Si necesitas soporte para Safari, puedes usar workers dedicados y de servicio, pero debes evitar un worker compartido. Si deseas actuar como un proxy HTTP, entonces debes usar un service worker. Un worker dedicado tiene un padre, un worker compartido tiene al menos un padre, y un service worker tiene al menos cero padres. Y luego, un worker dedicado muere con su padre, un worker compartido muere con su último padre y un service worker es un poco más complicado. Muy bien. Esa ha sido la presentación. Esta fue una comparación de los workers web. Si quieres seguirme, estoy en Twitter en tlhunter. Esta presentación está disponible en ese enlace bit.ly en línea. Y si estás interesado en obtener más información sobre el libro, no dudes en seguir ese último enlace también. ¡Gracias!
Comments