Command Palette

Search for a command to run...

Shared Workers: Compartir Estado Entre Múltiples Contextos

Aprende a usar Shared Workers para compartir datos y estado entre múltiples pestañas, ventanas e iframes del mismo origen, manteniendo sincronización en tiempo real.

Lectura: 15 min
Nivel: Intermedio

TL;DR - Resumen rápido

  • Los Shared Workers permiten compartir un worker entre múltiples contextos de navegación
  • Usan el sistema de puertos (MessagePort) para comunicación bidireccional
  • Pueden mantener estado compartido que persiste mientras haya conexiones activas
  • Son ideales para sincronización entre pestañas y comunicación en tiempo real
  • Se crean usando SharedWorker en lugar de Worker

Introducción a Shared Workers

Los Shared Workers son una extensión de los Web Workers que permiten compartir un único worker entre múltiples contextos de navegación. A diferencia de los Web Workers dedicados, que están vinculados a un solo contexto, un Shared Worker puede ser accedido por múltiples pestañas, ventanas e iframes del mismo origen simultáneamente.

Esta capacidad de compartir estado entre contextos hace que los Shared Workers sean ideales para aplicaciones que necesitan sincronización en tiempo real, comunicación entre pestañas, o mantener un estado compartido persistente. Por ejemplo, una aplicación de chat puede usar un Shared Worker para mantener la conexión WebSocket y distribuir mensajes a todas las pestañas abiertas.

  • <strong>Compartir estado</strong>: Mantener datos compartidos entre múltiples pestañas
  • <strong>Sincronización</strong>: Coordinar acciones entre diferentes contextos de navegación
  • <strong>Conexión persistente</strong>: Mantener una sola conexión a recursos externos
  • <strong>Comunicación broadcast</strong>: Enviar mensajes a múltiples contextos simultáneamente
  • <strong>Estado compartido</strong>: Los datos persisten mientras haya conexiones activas

Diferencia con Web Workers dedicados

Mientras que un Web Worker dedicado (Worker) está vinculado a un solo contexto y se destruye cuando ese contexto se cierra, un Shared Worker (SharedWorker) puede ser accedido por múltiples contextos simultáneamente y solo se destruye cuando todas las conexiones se cierran.

¿Qué es un Shared Worker?

Un Shared Worker es un tipo especial de Web Worker que puede ser compartido entre múltiples contextos de navegación del mismo origen. Cada contexto que se conecta al Shared Worker recibe un puerto (MessagePort) único que usa para comunicarse con el worker.

El Shared Worker mantiene una lista de todas las conexiones activas y puede enviar mensajes a todas ellas simultáneamente, lo que permite implementar patrones de broadcast y sincronización entre pestañas de forma eficiente. El worker persiste mientras haya al menos una conexión activa.

Limitación de origen

Los Shared Workers solo funcionan entre contextos del mismo origen. No puedes compartir un worker entre diferentes dominios. Si necesitas comunicación cross-origin, considera usar postMessage con validación de origen o Broadcast Channel API.

Crear un Shared Worker

Para crear un Shared Worker, usas el constructor SharedWorker en lugar de Worker. El constructor recibe la URL del archivo del worker como parámetro. A diferencia de los Web Workers dedicados, el SharedWorker tiene una propiedad ports que contiene los puertos de comunicación.

Archivo del Shared Worker

Primero, creemos el archivo del Shared Worker. Este archivo contiene el código que se ejecutará en el worker compartido. El worker escucha el evento connect para nuevas conexiones y mantiene una lista de puertos activos.

shared-worker.js
Loading code...

Este Shared Worker escucha el evento connect cada vez que un nuevo contexto se conecta. Cada conexión recibe un puerto único que se agrega a la lista de puertos activos. El worker puede enviar mensajes a todos los puertos simultáneamente para implementar broadcast.

Conectar al Shared Worker

Ahora creemos el código para conectar al Shared Worker desde un contexto de navegación. Cada contexto que se conecta recibe un puerto único que usa para comunicarse con el worker.

conectar-shared-worker.js
Loading code...

Este código muestra cómo conectar a un Shared Worker desde el hilo principal. La propiedad ports[0] contiene el puerto de comunicación que debes usar para enviar y recibir mensajes. El puerto debe iniciarse explícitamente con port.start().

Mejor práctica

Siempre inicia el puerto con port.start() antes de enviar mensajes. Sin esta llamada, el puerto no recibirá mensajes. También es buena práctica manejar el evento onerror para capturar errores en el worker.

Comunicación con Ports

La comunicación con un Shared Worker se realiza a través de puertos (MessagePort). Cada conexión tiene su propio puerto único que usa para comunicarse con el worker. Los puertos soportan comunicación bidireccional usando postMessage y el evento message.

Enviar Mensajes por el Puerto

Para enviar mensajes al Shared Worker, usas el método postMessage en el puerto. El mensaje puede ser cualquier dato que sea clonable según el algoritmo de clonación estructurada.

enviar-mensaje-port.js
Loading code...

Este ejemplo muestra cómo enviar mensajes al Shared Worker usando el puerto. El puerto también puede transferir objetos como ArrayBuffer para mejorar el rendimiento con datos grandes.

Recibir Mensajes del Puerto

Para recibir mensajes del Shared Worker, escuchas el evento message en el puerto. El evento contiene el mensaje en la propiedad data.

recibir-mensaje-port.js
Loading code...

Este ejemplo muestra cómo recibir mensajes del Shared Worker. El puerto escucha el evento message y procesa los mensajes recibidos. Puedes responder al worker usando el mismo puerto.

Broadcast de Mensajes

Una de las características más poderosas de los Shared Workers es la capacidad de enviar mensajes a todos los contextos conectados simultáneamente. Esto permite implementar sincronización en tiempo real entre pestañas.

broadcast-mensajes.js
Loading code...

Este ejemplo muestra cómo implementar broadcast en un Shared Worker. El worker mantiene una lista de puertos activos y puede enviar mensajes a todos ellos simultáneamente. Este patrón es ideal para sincronización en tiempo real, aplicaciones de chat, dashboards en vivo, o cualquier escenario donde múltiples pestañas necesitan mostrar los mismos datos.

Gestionar Conexiones

El Shared Worker debe gestionar las conexiones activas para mantener la integridad del sistema. Cuando un contexto se desconecta, el worker debe eliminar el puerto correspondiente de la lista de conexiones activas.

Detectar Desconexiones

Para detectar cuando un contexto se desconecta, escuchas el evento close en el puerto. Este evento se dispara cuando el puerto se cierra, lo que indica que el contexto ya no está disponible.

detectar-desconexion.js
Loading code...

Este ejemplo muestra cómo detectar desconexiones en un Shared Worker. El evento close se dispara cuando un puerto se cierra, permitiendo al worker eliminar el puerto de la lista de conexiones activas.

Limpiar Conexiones Inactivas

Es buena práctica limpiar conexiones inactivas periódicamente para evitar fugas de memoria. Puedes implementar un mecanismo que elimine puertos que no han enviado mensajes en un período de tiempo específico.

limpiar-conexiones.js
Loading code...

Este ejemplo muestra cómo implementar limpieza de conexiones inactivas. El worker verifica periódicamente qué puertos no han enviado mensajes recientemente y los elimina de la lista de conexiones activas.

Advertencia de memoria

Si no eliminas los puertos de contextos desconectados, puedes causar fugas de memoria en el Shared Worker. Siempre escucha el evento close en los puertos y elimínalos de la lista de conexiones activas.

Casos de Uso

Los Shared Workers son ideales para varios escenarios donde necesitas compartir estado o coordinar acciones entre múltiples contextos de navegación.

Sincronización Entre Pestañas

Un caso de uso común es sincronizar el estado entre múltiples pestañas de la misma aplicación. Por ejemplo, en una aplicación de gestión de tareas, cuando un usuario marca una tarea como completada en una pestaña, todas las demás pestañas deben reflejar este cambio.

sincronizacion-pestanas.js
Loading code...

Este ejemplo muestra cómo implementar sincronización de estado entre pestañas usando un Shared Worker. El worker mantiene el estado compartido y notifica a todas las pestañas cuando hay cambios.

Conexión Única a Recursos Externos

Los Shared Workers son ideales para mantener una sola conexión a recursos externos como WebSockets o APIs. Esto reduce la carga en el servidor y mejora el rendimiento al evitar múltiples conexiones desde el mismo cliente.

conexion-unica.js
Loading code...

Este ejemplo muestra cómo usar un Shared Worker para mantener una sola conexión WebSocket. Todas las pestañas se conectan al worker, y el worker mantiene la conexión única al servidor, distribuyendo los mensajes a todas las pestañas.

Rendimiento

Usar un Shared Worker para mantener una sola conexión a recursos externos mejora significativamente el rendimiento. En lugar de que cada pestaña mantenga su propia conexión, todas comparten la misma conexión, reduciendo la carga en el servidor y el ancho de banda.

Chat en Tiempo Real

Los Shared Workers son perfectos para implementar aplicaciones de chat en tiempo real donde múltiples pestañas del mismo usuario necesitan mostrar los mismos mensajes simultáneamente.

chat-tiempo-real.js
Loading code...

Este ejemplo muestra cómo implementar un chat en tiempo real usando un Shared Worker. El worker mantiene la conexión WebSocket y distribuye los mensajes a todas las pestañas conectadas, asegurando que todas muestren los mismos mensajes.

Resumen: Shared Workers

Conceptos principales:

  • Los Shared Workers se comparten entre múltiples contextos de navegación del mismo origen
  • Cada conexión tiene su propio MessagePort para comunicación bidireccional
  • El worker mantiene una lista de puertos activos para broadcast
  • El estado persiste mientras haya conexiones activas
  • Usan SharedWorker en lugar de Worker para crear el worker

Mejores prácticas:

  • Siempre inicia el puerto con port.start() antes de enviar mensajes
  • Escucha el evento close para detectar desconexiones y limpiar puertos
  • Usa broadcast para sincronizar estado entre múltiples pestañas
  • Mantén una sola conexión a recursos externos como WebSockets
  • Implementa limpieza de conexiones inactivas para evitar fugas de memoria