— tl;dr: Unmengen an Code im Folgenden —
Bei Wearable Intelligence benötigen wir eine zuverlässige Echtzeitverbindung für unsere Mitarbeiter im Außendienst. Vor allem müssen wir einen Offline-Zustand auf Web- und Mobil-Clients korrekt anzeigen.

Das Banner zur Wiederherstellung der Verbindung im Gmail-Stil ist zwar nichts Revolutionäres, aber wie wir es mit React und NuclearJS (der Flux-Implementierung, die wir nutzen und lieben) umsetzen, finde ich ziemlich cool. Nach einigen Iterationen haben wir die Tücken nativer WebSockets auf recht elegante Weise in den Griff bekommen. Hoffentlich findest du hier ein paar nützliche Informationen, falls du dich mit ähnlichen Themen beschäftigst.
Wegweiser
- React wird ausschließlich für die Benutzeroberfläche verwendet. Keine Geschäftslogik – es werden lediglich Verbindungen zu den Gettern von Nuclear hergestellt und Aktionen von Nuclear aufgerufen.
- Nuclear-Getter sind reine Funktionen, die Daten aus Speichern abrufen, und Nuclear-Speicher aktualisieren den Zustand ausschließlich auf Grundlage von Nuclear-Aktionen. Weder Nuclear-Getter noch Nuclear-Speicher führen selbst externe Aktionen aus.
- Die gesamte WebSocket-Logik ist sauber in einen Dienst isoliert, der vollständig außerhalb von Nuclear liegt.
- Nuclear-Aktionen verknüpfen alles miteinander, verwalten die Verbindung und reagieren auf Ereignisse im Zusammenhang mit der Benutzer- und Socket-Verwaltung.
React: Nur die Benutzeroberfläche, Ma’am
Wir nutzen einen „Signaling“-Server, um Echtzeitereignisse an Web- und Mobil-Clients zu übertragen. Um diese Funktion in eine unserer Web-Apps zu integrieren, müssen wir lediglich eine Signaling-Komponente in eine beliebige authentifizierte übergeordnete Komponente einbinden.
Mit „Nuclear“ können wir den Status der Signalverbindung als unveränderliche Map speichern. Wir können eine „connect“-Aktion auslösen, wenn die Komponente eingebunden wird und wenn der Benutzer dies ausdrücklich anfordert, und wir können die Verbindung trennen, wenn die Komponente entbunden wird.
Der Rest ist UI. Für unsere Designer ist es kinderleicht zu erkennen, wie das Ganze funktioniert, ohne sich Gedanken über die dahinterstehende Technik machen zu müssen, und sie können das Markup oder das zugehörige SCSS ganz unkompliziert bearbeiten. Zack.
Der WebSocket-Anbieter: Singletons sorgfältig einschränken
Früher war die Einrichtung von Echtzeitverbindungen dank Socket.io viel einfacher, aber in diesem Fall müssen wir WebSockets nativ erstellen und verwalten, um eine Verbindung zu einem bestehenden Server herzustellen (vielleicht ein Thema für einen anderen Beitrag).
Das Problem dabei ist, dass wir in Nuclear-Aktionen auf die aktuelle Socket-Instanz verweisen müssen. Daher benötigen wir ein Singleton, das wir persistent speichern und verändern können – etwas, das am besten komplett aus Nuclear herausgehalten werden sollte.
Dieser Anbieter kann problemlos aus jeder Aktion heraus aufgerufen werden, und man kann sich darauf verlassen, dass er die aktuelle Instanz bereitstellt. Wie gewünscht, kann die Instanz hart zurückgesetzt werden, was während des Wiederverbindungsvorgangs leider notwendig ist.
Als zusätzlichen Vorteil verwaltet der Anbieter zudem eine permanente Übersicht über die Timer, wodurch vermieden wird, dass „Nuclear“-Speicher Intervalle einstellen und löschen müssen.
Unsere spezielle Socket-Implementierung erfordert, dass wir den Server etwa alle 30 Sekunden mit einem Präsenzpaket anpingen. Der Provider verfügt daher über diese integrierte Funktion und verwaltet eine Zuordnung zwischen Nachrichtentypen und den entsprechenden Handlern (von denen jeder Nuclear-Aktionen aus anderen Modulen aufruft).
Nukleare Maßnahmen: Die Arbeitspferde
Um alles übersichtlich und klar zu halten, wollen wir nur die Aktionen „Verbinden“ und „Trennen“ nach außen hin verfügbar machen. Alles andere ist ein internes Implementierungsdetail.
„Connect“ ist die einzige Methode, die durch die Übergabe von „true“ als drittes Argument einen Hard-Reset des Sockets auslöst. Andere Instanziierungen des WebSocketProviders geben einfach die vorhandene Instanz zurück.
In den übrigen internen Funktionen spielt sich das eigentliche Geschehen ab. Die Ereignisbehandler starten und stoppen zudem die entsprechenden Timer.
Befindet sich die Verbindung im Bereitschaftszustand, löst der Identifikations -Timer alle 30 Sekunden einen Ping aus, wodurch unsere Anwesenheitsanforderung für den Signalisierungsserver selbst erfüllt wird.
Wenn die Verbindung geschlossen wird oder „kalt“ wird (kein Close-Ereignis, aber seit über einer Minute keine Antwort auf Pings), wird der Identify-Timer angehalten und der Reconnect-T imer gestartet. Jede Sekunde wird die Aktion `UPDATE_RECONNECT_TIMER` ausgelöst, die unser Store nutzt, um seinen Status zu aktualisieren, sodass sich unsere React-Komponente nicht selbst darum kümmern muss.
Da der WebSocketProvider vor der Festlegung des Intervalls prüft, ob bereits ein Timer vorhanden ist, besteht keine Gefahr, dass Funktionen wie „checkConnection“ zu oft aufgerufen werden.
Das Debuggen mit NuclearJS ist ein wahr gewordener Traum
Wann hast du das das letzte Mal gehört? Folgendes sehe ich, wenn ich eine neue Änderung debugge:

Jedes dieser Protokollobjekte lässt sich aufklappen, um sowohl die Aktionsdaten als auch den App-Status zu diesem Zeitpunkt anzuzeigen. Man muss nicht mehr überall ` console.log ` einfügen, um festzustellen, was zwischen den Ereignissen passiert ist.
In diesem Fall können Sie bei der Anmeldung beobachten, wie die App einen Verbindungsversuch startet, die Statusänderung meldet, sobald die Verbindung hergestellt ist, einen Präsenz-Ping sendet und das Ergebnis empfängt. 30 Sekunden später gehen ein Identifizierungs- und ein Empfangs-Ping ein.
Dann habe ich den Signalisierungsserver manuell (lokal!) beendet, und man sieht, wie das „Close“-Ereignis eintrifft, gefolgt von einem sofortigen, aber erfolglosen Versuch, die Verbindung wiederherzustellen. Der Timer für die Wiederherstellung der Verbindung wird jede Sekunde aktualisiert, aber sobald ich die Signalisierung wieder aktiviere, erhalten wir die erwarteten Verbindungsereignisse.
Beim Abmelden werden alle Verbindungen getrennt und die Systemressourcen bereinigt, woraufhin die Anmeldeseite angezeigt wird.
Wenn du das hier hilfreich fandest, zögere nicht, es weiterzuempfehlen.
Ach ja, und wir suchen gerade unseren dritten Front-End-Entwickler – falls du Lust hast, bei einem Start-up der Serie A, das unter anderem von Andreessen Horowitz, First Round, Kleiner Perkins und Google Ventures finanziert wird, gegen Bezahlung mit React, Nuclear und ImmutableJS zu experimentieren.











