Tema representativo de entrevista

Entrevista Frontend: Diseñar una sincronización segura entre pestañas con BroadcastChannel

FrontendDifícil
Equipo editorial de Offer.ccPublicado Actualizado

Pregunta

Una consola de administración permite al usuario abrir varias pestañas. Después de que el usuario cierra sesión, cambia de tema o actualiza las notificaciones en una pestaña, las demás deben converger rápidamente. Las recargas de página, las pestañas suspendidas, los mensajes duplicados y los navegadores sin soporte para BroadcastChannel no deben corromper el estado final. Diseñe el protocolo, la recuperación, el mecanismo de respaldo y las métricas de verificación.

Planteamiento y contexto

Una consola de administración permite al usuario abrir varias pestañas. Después de que el usuario cierra sesión, cambia de tema o actualiza las notificaciones en una pestaña, las demás deben converger rápidamente. Las recargas de página, las pestañas suspendidas, los mensajes duplicados y los navegadores sin soporte para BroadcastChannel no deben corromper el estado final. Diseñe el protocolo, la recuperación, el mecanismo de respaldo y las métricas de verificación.

Esta es una pregunta de coordinación en el navegador orientada a roles de frontend, plataforma web y diseño de sistemas frontend. La cantidad de pestañas, el retraso de sincronización y los tipos de eventos son supuestos de la entrevista, no garantías del navegador. Concéntrese en los límites de mismo origen y partición de almacenamiento de BroadcastChannel, las consecuencias de los mensajes no persistentes, la elección entre evento versus estado y cuándo combinarlo con localStorage, IndexedDB, SharedWorker o Web Locks.

Qué está evaluando el entrevistador

Primero, ¿puede definir el límite de la API? BroadcastChannel envía mensajes entre ventanas, pestañas, frames y workers que comparten un origen y una partición de almacenamiento comunicable. No es un transporte de origen cruzado, ni una cola duradera, ni un servicio de consistencia distribuida.

Segundo, ¿puede diseñar un protocolo idempotente? Los mensajes pueden duplicarse, el emisor no recibe su propia difusión y una página receptora puede cerrarse o suspenderse. Un mensaje que solo diga “el tema cambió” sin una versión y una ruta de relectura deja el estado permanentemente desactualizado.

Tercero, ¿puede separar las notificaciones de la fuente de la verdad? El cierre de sesión puede difundir una invalidación, los cambios de tema pueden persistirse y luego anunciarse, y una actualización de notificaciones debe hacer que los receptores vuelvan a leer una caché autoritativa en lugar de tratar una lista completa en el mensaje como la verdad.

Finalmente, ¿puede manejar el ciclo de vida y los mecanismos de respaldo: cerrar canales, mantener tokens fuera de los mensajes, detectar capacidades, usar eventos de almacenamiento o relecturas del servidor y medir que la sincronización no cree bucles ni fugas de memoria?

Preguntas para aclarar primero

  • ¿La carga útil es un evento único, el estado actual o un historial reproducible? Eso determina si se requiere una versión persistente.
  • ¿El alcance es un solo origen, un iframe bajo el mismo sitio de nivel superior o diferentes subdominios? Una partición de almacenamiento puede impedir la comunicación incluso cuando los orígenes parecen relacionados.
  • ¿Se puede perder un mensaje? El cierre de sesión, la revocación de permisos y los conflictos de edición necesitan diferentes garantías de recuperación.
  • ¿Dónde está la fuente de la verdad: servidor, IndexedDB, localStorage, una caché en memoria o un Service Worker?
  • ¿Debe una sola pestaña ser el único escritor para recargas, migraciones o trabajo por lotes? BroadcastChannel no proporciona un bloqueo.
  • ¿Cuál es la matriz de navegadores, incluyendo el modo incógnito, la suspensión en segundo plano y la cantidad esperada de pestañas?
  • ¿Podría un mensaje contener datos de perfil, permisos o un token? De ser así, reemplácelo con una señal de invalidación no sensible.

Una respuesta de 30 segundos

“Usaría BroadcastChannel como un bus de notificaciones de baja latencia, no como una fuente de estado duradera. Cada mensaje lleva una versión de protocolo, tipo de evento, secuencia monótona o versión de estado y trace ID. Los receptores validan la estructura, aplican el evento de forma idempotente y vuelven a leer localStorage, IndexedDB o el servidor cuando aparece una brecha de versión. El cierre de sesión envía una invalidación, el tema escribe preferencias persistentes y los cambios de notificación activan una relectura. Si la API no está disponible, se usan eventos de almacenamiento o sondeo (polling); si se requiere un único escritor, se usan Web Locks o coordinación del servidor. Cierre cada canal al desmontar y mida la latencia, la recuperación de mensajes perdidos y el manejo de duplicados.”

Respuesta paso a paso

Paso 1: Definir los mensajes y el estado autoritativo

Asigne una fuente de la verdad por funcionalidad. El tema y el idioma son preferencias que pueden residir en configuraciones persistentes. Las notificaciones y los permisos deben releerse desde el servidor o una caché local. El cierre de sesión es una señal de invalidación de sesión; nunca coloque un token de acceso en un mensaje. Difunda únicamente type, version, entityKey, updatedAt o traceId no sensibles.

MDN explica que BroadcastChannel admite comunicación bidireccional entre contextos de navegación y workers del mismo origen, mientras que la aplicación define el protocolo del mensaje; la plataforma no proporciona negociación. El versionado, el manejo de eventos desconocidos y la validación de campos son responsabilidades de la aplicación.

Paso 2: Manejar duplicados, ordenamiento y pérdidas

Mantenga la última versión procesada para cada dominio de estado. Ignore un mensaje cuya versión sea anterior o igual; una versión contigua más nueva puede activar una relectura; un salto indica una brecha e inicia una sincronización por snapshot. Si el negocio expone eventos sin versiones, use un ID de deduplicación y un conjunto procesado acotado, admitiendo que esto no puede probar que un evento intermedio no se haya perdido.

No asuma la entrega. El emisor no recibe su propio mensaje, y una pestaña recién abierta o suspendida puede perderlo. Al iniciar, cargue el estado persistente o un snapshot del servidor antes de suscribirse; la difusión solo reduce la latencia de actualización.

Paso 3: Elegir la persistencia y la coordinación en conjunto

localStorage se adapta a preferencias pequeñas y puede activar un evento de almacenamiento; no es una base de datos de alto rendimiento ni un lugar para tokens. IndexedDB se adapta a cachés locales más grandes y snapshots versionados. Un Service Worker puede participar en la sincronización en segundo plano, pero debe escribir los resultados en un almacenamiento recuperable.

BroadcastChannel resuelve la notificación a múltiples contextos, no la coordinación de un único escritor. Si una sola pestaña debe actualizar una caché, ejecutar una migración o enviar un lote, use Web Locks. Sin el bloqueo, incluya una condición de versión y deje que el servidor arbitre. Un SharedWorker se adapta a conexiones compartidas o estado centralizado, pero añade complejidad de ciclo de vida y compatibilidad.

Paso 4: Construir una recepción segura y mecanismos de respaldo

Acepte solo tipos de eventos en lista blanca, limite el tamaño del mensaje y rechace versiones desconocidas o esquemas inválidos. Nunca coloque un token de acceso, un perfil completo o HTML ejecutable en un mensaje. Al cerrar sesión, limpie las cachés locales sensibles y navegue a la página de inicio de sesión; ante un evento de tema, actualice la UI pero confíe en la configuración persistida.

Si la detección de capacidades falla, use eventos de almacenamiento para estados pequeños. Si eso no está disponible o está particionado, vuelva a leer al obtener el foco, use sondeo breve o recurra al push del servidor. Un mecanismo de respaldo debe ser seguro de repetir; la falta de difusión no puede convertirse en una divergencia permanente.

Paso 5: Administrar recursos y verificar el comportamiento

Elimine los listeners y llame a close() cuando un componente o página se destruya. No cree un canal nuevo en cada render. Use un espacio de nombres para que aplicaciones no relacionadas no se suscriban al mismo nombre. Incluya una etiqueta de origen y un trace ID para que un receptor no vuelva a difundir el mismo mensaje en bucle.

Pruebe el retraso de extremo a extremo entre múltiples pestañas, duplicados y reordenamiento, reanudación tras suspensión, el snapshot inicial tras recargar, respaldo en almacenamiento, aislamiento por partición de almacenamiento, cierre de canales, mensajes sobredimensionados, bucles y cambio de usuario. Monitoree el éxito de los manejadores, brechas de versión, relecturas, duplicados descartados, tiempo de recuperación y canales que quedaron abiertos.

Respuesta modelo de alta calidad

“Definiría BroadcastChannel como un bus de notificaciones, no como una cola. El cierre de sesión lleva únicamente un tipo de invalidación de sesión y una versión. Una actualización de tema escribe en localStorage y difunde la nueva versión de preferencia. Una actualización de notificación difunde una clave de entidad y una versión, de modo que cada receptor vuelve a leer desde el servidor o IndexedDB. Los mensajes no contienen tokens ni datos de usuario completos.

Cada mensaje tiene una versión de protocolo, una versión de estado monótona y un trace ID. Los receptores rechazan estructuras desconocidas, descartan versiones procesadas o más antiguas y obtienen un snapshot cuando detectan una brecha. El inicio carga un snapshot antes de suscribirse porque una pestaña nueva o suspendida puede perderse una difusión, y el emisor no recibe su propio mensaje.

Si la actualización de caché necesita un único escritor, añadiría Web Locks; BroadcastChannel por sí solo no puede evitar que dos pestañas escriban concurrentemente. Los navegadores no compatibles usan eventos de almacenamiento para preferencias pequeñas y relecturas al enfocar o sondeo corto para otros datos. El desmontaje elimina listeners y cierra el canal. Las métricas cubren retraso, brechas, duplicados, tiempo de recuperación y recursos filtrados. Esto separa la notificación de baja latencia, el estado recuperable y la compatibilidad del navegador.”

Modos de fallo comunes

  • Tratar la difusión como una cola duradera → las pestañas nuevas o suspendidas pierden eventos → cargue un snapshot primero y use los mensajes como pistas.
  • Poner tokens o el estado completo en los mensajes → amplía la exposición de datos sensibles y los conflictos de versión → envíe solo eventos, claves y versiones no sensibles.
  • Sin versión o ID de deduplicación → los duplicados y el desorden retroceden la UI → use versiones monótonas, manejo idempotente y relecturas ante brechas.
  • Asumir que el mismo origen garantiza conectividad → la partición de almacenamiento puede aislar contextos → pruebe el límite real y proporcione un mecanismo de respaldo.
  • Usar BroadcastChannel como un bloqueo → dos pestañas aún pueden escribir concurrentemente → use Web Locks o escrituras condicionales en el servidor.
  • Crear un canal en cada render → se filtran listeners y recursos → mantenga una instancia estable, elimine listeners y ciérrelo.
  • Redifundir cada mensaje recibido → crea un bucle → transporte IDs de origen/rastreo y envíe solo ante cambios de estado.
  • Tratar los eventos de almacenamiento como un reemplazo completo → solo cubren algunas escrituras y no la misma ventana → documente la diferencia y agregue relecturas.

Preguntas de seguimiento

Pregunta de seguimiento 1: Dos pestañas editan el mismo formulario. ¿Cómo evita la sobrescritura?

Difunda que la versión del recurso cambió; no sobrescriba el borrador local. Envíe una versión base, permita que el servidor rechace escrituras condicionales desactualizadas y muestre un conflicto para la combinación manual del usuario. Una preferencia local puede usar Web Locks para escrituras serializadas.

Pregunta de seguimiento 2: Una pestaña se activa después de estar suspendida durante 20 minutos. ¿Cómo se pone al día?

Vuelva a leer un snapshot del servidor o IndexedDB al reanudar, compare las versiones de estado y luego procese cualquier señal incremental. No confíe en la última difusión. Si el snapshot no está disponible, marque el estado como obsoleto y requiera revalidación o muestre un estado expirado claro.

Pregunta de seguimiento 3: Páginas en diferentes subdominios necesitan comunicarse. ¿Lo resuelve BroadcastChannel?

No asuma que lo hace. BroadcastChannel está restringido por origen y partición de almacenamiento. La comunicación de origen cruzado necesita una relación de ventana explícita con postMessage o coordinación del servidor, con verificaciones de origen, esquema y permisos; no debilite el límite de seguridad solo para compartir un canal.

Pregunta de seguimiento 4: Solo una pestaña debe mantener un WebSocket. ¿Cómo lo diseñaría?

BroadcastChannel puede compartir el estado y los datos de la conexión, pero no puede elegir un líder. Prefiera Web Locks para el titular, con las demás pestañas suscribiéndose a sus difusiones; vuelva a elegir después de que el titular se cierre o pierda el bloqueo. Si no está disponible, use un arrendamiento (lease) del servidor o permita múltiples conexiones con deduplicación en el servidor y una compensación de costos explícita.

Fuentes públicas

Preguntas relacionadas