— En resumen: a continuación hay mucho código —
En Wearable Intelligence necesitamos una conexión fiable en tiempo real para los trabajadores que se encuentran sobre el terreno. Y lo más importante: necesitamos mostrar con precisión el estado de desconexión en los clientes web y móviles.

El banner de reconexión al estilo de Gmail no tiene nada de revolucionario, pero la forma en que lo gestionamos utilizando React y NuclearJS (la implementación de Flux que usamos y nos encanta) me parece bastante interesante, y tras unas cuantas iteraciones hemos logrado dominar con bastante elegancia las peculiaridades de los WebSockets nativos. Espero que encuentres aquí algo útil si estás trabajando en ámbitos similares.
Puntos de referencia
- React se utiliza únicamente para la interfaz de usuario. No hay lógica de negocio: simplemente se vinculan a los getters de Nuclear y llaman a las acciones de Nuclear.
- Los «getters» de Nuclear son funciones puras que extraen datos de los «stores», y los «stores» de Nuclear solo actualizan el estado en función de las acciones de Nuclear. Ni los «getters» ni los «stores» de Nuclear realizan por sí mismos ninguna acción externa.
- Toda la lógica de WebSocket está perfectamente aislada en un servicio totalmente independiente de Nuclear.
- Las acciones nucleares lo coordinan todo, gestionando la conexión y respondiendo a los eventos de mantenimiento de los usuarios y los sockets.
React: Solo la interfaz de usuario, señora
Utilizamos un servidor de «Signaling» para transmitir eventos en tiempo real a clientes web y móviles. Para incorporar esta funcionalidad a cualquiera de nuestras aplicaciones web, solo tenemos que incluir un componente de Signaling en cualquier componente padre autenticado.
Nuclear nos permite almacenar el estado de la conexión de señalización como un mapa inmutable. Podemos activar una acción de conexión cuando se monta el componente y cuando el usuario la solicita explícitamente, y podemos desconectarnos cuando se desmonta el componente.
El resto es la interfaz de usuario. Para nuestros diseñadores es muy sencillo ver cómo funciona todo sin tener que pensar en toda la maquinaria que lo hace posible, y pueden editar sin problemas el código HTML o el SCSS correspondiente. ¡Y listo!
El proveedor de WebSocket: cómo gestionar con cuidado los singletons
Antes, mi experiencia con las conexiones en tiempo real era mucho más sencilla gracias al uso de Socket.io, pero en este caso tenemos que crear y gestionar WebSockets de forma nativa para conectarnos a un servidor ya existente (quizá ese sea un tema para otra entrada).
La dificultad radica en que necesitaremos que las acciones de Nuclear hagan referencia a la instancia actual del socket, por lo que necesitamos un singleton que podamos persistir y modificar, algo que es mejor mantener completamente al margen de Nuclear.
Este proveedor se puede invocar de forma segura desde cualquier acción y se puede confiar en que proporcionará la instancia actual. Tal y como se ha solicitado, la instancia se puede reiniciar por completo, lo cual es una necesidad desafortunada durante el proceso de reconexión.
Además, el proveedor mantiene un mapa permanente de temporizadores, lo que evita que las tiendas Nuclear tengan que configurar y borrar los intervalos.
Nuestra implementación específica del socket requiere que enviemos un paquete de presencia al servidor cada ~30 segundos, por lo que el proveedor incorpora esta funcionalidad y mantiene una tabla que relaciona los tipos de mensajes con sus controladores (cada uno de los cuales invoca acciones de Nuclear procedentes de otros módulos).
Acciones nucleares: los pilares fundamentales
Para que todo quede claro y ordenado, solo queremos mostrar las acciones «conectar» y «desconectar». Todo lo demás son detalles de implementación interna.
«Connect» es el único método que provoca un reinicio completo del socket al pasar «true» como tercer argumento. Las demás instanciaciones de WebSocketProvider simplemente devuelven la instancia existente.
El resto de las funciones internas son donde realmente se desarrolla la acción. Los controladores de eventos también inician y detienen los temporizadores correspondientes.
Si la conexión está lista, el temporizador de identificación envía un ping cada 30 segundos, lo que cumple con nuestro requisito de presencia para el propio servidor de señalización.
Si la conexión se cierra o se «enfría» (no se produce un evento de cierre, pero no hay respuesta a los pings durante más de un minuto), se detiene el temporizador de identificación y se inicia el temporizador de reconexión. Cada segundo se dispara la acción UPDATE_RECONNECT_TIMER, que nuestra tienda utiliza para actualizar su estado, de modo que nuestro componente React no tenga que ocuparse de ello.
Dado que WebSocketProvider comprueba si existe un temporizador antes de establecer el intervalo, no hay riesgo de que funciones como checkConnection se ejecuten demasiadas veces.
La depuración con NuclearJS es un sueño hecho realidad
¿Cuándo fue la última vez que oíste eso? Esto es lo que veo cuando depuro un nuevo cambio:

Cualquiera de esos objetos de registro se puede desplegar para mostrar la carga útil de la acción, así como el estado de la aplicación en ese momento concreto. Ya no hace falta incluir `console.log` por todas partes para determinar qué ha ocurrido entre un evento y otro.
En este caso, al iniciar sesión, se puede observar cómo la aplicación inicia un intento de conexión, notifica el cambio de estado cuando se establece la conexión, envía un ping de presencia y recibe el resultado. Un par de pings de identificación y recepción llegan 30 segundos después.
A continuación, detuve el servidor de señalización manualmente (¡a nivel local!), y se puede ver cómo se produce el evento de cierre, seguido de un intento inmediato de reconexión que no prospera. El temporizador de reconexión se actualiza cada segundo, pero en cuanto vuelvo a activar la señalización, recibimos los eventos de conexión esperados.
Al cerrar sesión, todo se desconecta y se borra, y aparece nuestra página de inicio de sesión.
Si te ha resultado útil, no dudes en recomendarlo.
Ah, sí, y estamos buscando a nuestro tercer ingeniero de front-end, por si te apetece que te paguen por darlo todo con React, Nuclear e ImmutableJS en una startup financiada en la ronda Serie A y respaldada por Andreessen Horowitz, First Round, Kleiner Perkins y Google Ventures, entre otros.











