In dem heutigen Artikel werde ich zeigen, wie man eine Webanwendung erstellt, die Live-Spielergebnisse der NHL anzeigt. Die Ergebnisse werden automatisch mit dem Fortschreiten der Spiele aktualisiert.
Dies ist ein sehr aufregender Artikel für mich, da ich zwei meiner Lieblingsleidenschaften zusammenbringen kann: Entwicklung und Sport.
Die Technologien, die zum Erstellen der Anwendung verwendet werden, sind:
Wenn Sie Node.js nicht installiert haben, besuchen Sie jetzt die Download-Seite und richten Sie sie ein, bevor Sie fortfahren.
Socket.io ist eine Technologie, die einen Client mit einem Server verbindet. In diesem Beispiel ist der Client ein Webbrowser und der Server ist die Anwendung Node.js. Der Server kann gleichzeitig mit mehreren Clients verbunden sein.
Nachdem die Verbindung hergestellt wurde, kann der Server Nachrichten an alle Clients oder einen einzelnen Client senden. Im Gegenzug kann der Client eine Nachricht an den Server senden, wodurch eine bidirektionale Echtzeitkommunikation ermöglicht wird.
Vor Socket.io verwendeten Webanwendungen normalerweise AJAX, und sowohl der Client als auch der Server würden sich gegenseitig nach Ereignissen abfragen. Zum Beispiel würde alle 10 Sekunden ein AJAX-Anruf erfolgen, um zu sehen, ob Nachrichten zu behandeln sind.
Das Abfragen von Nachrichten verursachte einen erheblichen Overhead sowohl auf dem Client als auch auf dem Server, da ständig nach Nachrichten gesucht würde, wenn keine vorhanden waren.
Mit Socket.io werden Nachrichten sofort empfangen, ohne nach Nachrichten suchen zu müssen, wodurch der Aufwand reduziert wird.
Bevor wir die Echtzeit-Sportdaten verbrauchen, erstellen wir eine Beispielanwendung, um zu zeigen, wie Socket.io funktioniert.
Zu Beginn werde ich eine neue Node.js-Anwendung erstellen. Ich werde in einem Konsolenfenster zu C: \ GitHub \ NodeJS navigieren, einen neuen Ordner für meine Anwendung erstellen und eine neue Anwendung erstellen:
cd \ GitHub \ NodeJS mkdir SocketExample cd SocketExample npm init
Ich habe alle Standardeinstellungen verwendet.
Da wir eine Webanwendung erstellen, verwende ich ein NPM-Paket namens Express, um die Einrichtung zu vereinfachen. Installieren Sie es in einer Eingabeaufforderung wie folgt: npm install express --save
Und natürlich müssen wir das Socket.io-Paket installieren: npm install socket.io --save
Beginnen wir mit der Erstellung des Webservers. Erstellen Sie eine neue Datei mit dem Namen index.js und fügen Sie den folgenden Code ein, um den Webserver mit Express zu erstellen:
var app = requir ('express') (); var http = required ('http'). Server (App); app.get ('/', Funktion (req, res) res.sendFile (__ dirname + '/index.html');); http.listen (3000, function () console.log ('HTTP-Server wurde an Port 3000 gestartet'););
Wenn Sie mit Express nicht vertraut sind, enthält das obige Codebeispiel die Express-Bibliothek und erstellt einen neuen HTTP-Server. In diesem Beispiel überwacht der HTTP-Server den Port 3000, z. http: // localhost: 3000. Eine Route wird im Stammverzeichnis der Site "/" erstellt. Das Ergebnis der Route gibt eine HTML-Datei zurück: index.html.
Bevor wir die index.html-Datei erstellen, beenden Sie den Server, indem Sie Socket.io einrichten. Hängen Sie der Datei index.js Folgendes an, um den Socket-Server zu erstellen:
var io = erfordern ('socket.io') (http); io.on ('Verbindung', Funktion (Socket) console.log ('Client-Verbindung erhalten'););
Ähnlich wie bei Express beginnt der Code mit dem Importieren der Bibliothek Socket.io. Dies wird in einer aufgerufenen Variablen gespeichert io
. Als nächstes verwenden Sie die io
Variable wird ein Event-Handler mit der erstellt auf
Funktion. Das Ereignis, das überwacht wird, ist die Verbindung. Dieses Ereignis wird jedes Mal aufgerufen, wenn ein Client eine Verbindung zum Server herstellt.
Lassen Sie uns jetzt unseren sehr einfachen Kunden erstellen. Erstellen Sie eine neue Datei namens index.html und fügen Sie den folgenden Code ein:
Socket.IO-Beispiel
Der obige HTML-Code lädt das JavaScript des Socket.io-Clients und initialisiert eine Verbindung zum Server. Starten Sie Ihre Node-Anwendung, um das Beispiel anzuzeigen: Knoten index.js
Navigieren Sie dann in Ihrem Browser zu http: // localhost: 3000. Auf der Seite wird nichts angezeigt. Wenn Sie jedoch die Konsole betrachten, auf der die Node-Anwendung ausgeführt wird, werden zwei Meldungen protokolliert:
Nun, da wir eine erfolgreiche Socket-Verbindung haben, setzen wir sie ein. Beginnen wir mit dem Senden einer Nachricht vom Server an den Client. Wenn der Client die Nachricht dann empfängt, kann er eine Antwort an den Server zurücksenden.
Schauen wir uns die abgekürzte Datei index.js an:
io.on ('Verbindung', Funktion (Socket) Konsole.log ('Client-Verbindung erhalten')); Socket.emit ('sendToClient', Hallo: 'Welt'); Socket.on ('receiveFromClient', Funktion (data) console.log (data);););
Der Vorherige io.on
Die Funktion wurde um einige neue Codezeilen erweitert. Der Erste, socket.emit
, sendet die Nachricht an den Client. Das sendToClient
ist der Name der Veranstaltung. Durch die Benennung von Ereignissen können Sie verschiedene Arten von Nachrichten senden, damit der Client sie unterschiedlich interpretieren kann. Der zweite Zusatz ist der Socket.on
, die auch einen Veranstaltungsnamen enthält: receiveFromClient
. Dadurch wird eine Funktion erstellt, die Daten vom Client akzeptiert. In diesem Fall werden die Daten im Konsolenfenster protokolliert.
Damit sind die serverseitigen Änderungen abgeschlossen. Es kann jetzt Daten von allen verbundenen Clients senden und empfangen.
Vervollständigen Sie dieses Beispiel, indem Sie den Client so aktualisieren, dass er die sendToClient
Veranstaltung. Wenn es das Ereignis empfängt, kann es mit dem antworten receiveFromClient
Ereignis zurück an den Server.
Dies geschieht im JavaScript-Teil des HTML-Codes. In der Datei index.html habe ich das JavaScript wie folgt aktualisiert:
var socket = io (); socket.on ('sendToClient', Funktion (Daten) console.log (data); socket.emit ('receiveFromClient', my: 'data'););
Mit der instantiierten Socketvariablen haben wir eine sehr ähnliche Logik auf dem Server mit a Socket.on
Funktion. Für den Kunden hört er auf sendToClient
Veranstaltung. Sobald der Client verbunden ist, sendet der Server diese Nachricht. Wenn der Client sie empfängt, wird er im Browser an der Konsole angemeldet. Der Client verwendet dann dasselbe socket.emit
dass der Server das ursprüngliche Ereignis gesendet hat. In diesem Fall sendet der Client die receiveFromClient
Ereignis an den Server. Wenn der Server die Nachricht empfängt, wird sie im Konsolenfenster protokolliert.
Probieren Sie es selbst aus. Führen Sie zunächst in einer Konsole Ihre Node-Anwendung aus: Knoten index.js
. Laden Sie dann http: // localhost: 3000 in Ihren Browser.
Überprüfen Sie die Webbrowser-Konsole. Es sollten die folgenden JSON-Daten protokolliert werden: Hallo Welt"
In der Eingabeaufforderung, an der die Node-Anwendung ausgeführt wird, sollte dann Folgendes angezeigt werden:
HTTP-Server wurde an Port 3000 gestartet. Clientverbindung empfangen my: 'data'
Sowohl der Client als auch der Server können die erhaltenen JSON-Daten verwenden, um bestimmte Aufgaben auszuführen. Wir werden mehr darüber erfahren, sobald wir uns mit den Echtzeit-Sportdaten verbinden.
Nun, da wir das Senden und Empfangen von Daten an und von Client und Server beherrschen, kann dies für Echtzeitaktualisierungen genutzt werden. Ich habe mich für Sportdaten entschieden, obwohl dieselbe Theorie nicht auf Sport beschränkt ist. Bevor ich dieses Projekt begann, habe ich verschiedene Sportdaten recherchiert. Ich entschied mich für MySportsFeeds (ich bin mit ihnen in keiner Weise verbunden), weil sie kostenlose Entwicklerkonten anbieten. Um auf die Echtzeitdaten zugreifen zu können, habe ich mich für ein Konto angemeldet und dann eine kleine Spende gemacht. Spenden beginnen bei $ 1, um die Daten alle 10 Minuten zu aktualisieren. Das wird für das Beispiel gut sein.
Sobald Ihr Konto eingerichtet ist, können Sie mit dem Einrichten des Zugriffs auf die API fortfahren. Um dies zu unterstützen, werde ich ihr NPM-Paket verwenden: npm install mysportsfeeds-node --save
Nachdem das Paket installiert wurde, können API-Aufrufe wie folgt ausgeführt werden:
var MySportsFeeds = required ("mysportsfeeds-node"); var msf = new MySportsFeeds ("1.2", true); msf.authenticate ("********", "*********"); var heute = neues Datum (); msf.getData ('nhl', '2017-2018-regular', 'scoreboard', 'json', fordate: today.getFullYear () + ('0' + parseInt (today.getMonth () + 1)). slice (-2) + ('0' + today.getDate ()). slice (-2), force: true);
Stellen Sie sicher, dass Sie im obigen Beispiel den Aufruf der Authentifizierungsfunktion durch Ihren Benutzernamen und Ihr Kennwort ersetzen.
Der folgende Code führt einen API-Aufruf aus, um die NHL-Anzeigetafel für heute abzurufen. Das für Datum
Variable ist, was heute spezifiziert. Hab ich auch eingestellt Macht
zu wahr
so dass immer eine Antwort zurückgegeben wird, auch wenn sich die Daten nicht geändert haben.
Mit dem aktuellen Setup werden die Ergebnisse des API-Aufrufs in eine Textdatei geschrieben. Im letzten Beispiel wird dies geändert. Zu Demonstrationszwecken kann die Ergebnisdatei jedoch in einem Texteditor überprüft werden, um den Inhalt der Antwort zu verstehen. Die Ergebnisse enthalten ein Anzeigetafelobjekt. Dieses Objekt enthält ein Array namens gameScore
. Dieses Objekt speichert das Ergebnis jedes Spiels. Jedes Objekt enthält ein untergeordnetes Objekt Spiel
. Dieses Objekt liefert die Informationen darüber, wer gerade spielt.
Außerhalb des Spielobjekts gibt es eine Handvoll Variablen, die den aktuellen Status des Spiels angeben. Die Daten ändern sich je nach Status des Spiels. Wenn das Spiel beispielsweise noch nicht gestartet ist, gibt es nur wenige Variablen, die uns sagen, dass das Spiel nicht läuft und noch nicht begonnen hat.
Wenn das Spiel läuft, werden zusätzliche Daten über die Punktzahl, den Zeitraum, in dem sich das Spiel befindet, und die verbleibende Zeit angezeigt. Wir werden dies in Aktion sehen, wenn wir zu HTML gelangen, um das Spiel im nächsten Abschnitt zu zeigen.
Wir haben alle Teile des Puzzles, also ist es jetzt an der Zeit, das Puzzle zusammenzusetzen, um das endgültige Bild zu zeigen. Momentan hat MySportsFeeds nur eine begrenzte Unterstützung für die Weitergabe von Daten an uns, daher müssen wir die Daten von ihnen abfragen. Glücklicherweise wissen wir, dass sich die Daten nur alle 10 Minuten ändern, sodass wir nicht zu viel Aufwand hinzufügen müssen, indem zu häufig Änderungen nachgefragt werden. Sobald wir die Daten von ihnen abfragen, können wir diese Updates vom Server an alle verbundenen Clients übertragen.
Um die Abfrage durchzuführen, verwende ich das JavaScript setInterval
Funktion, um die API (in meinem Fall) alle 10 Minuten aufzurufen, um nach Updates zu suchen. Wenn die Daten empfangen werden, wird ein Ereignis an alle verbundenen Clients gesendet. Wenn die Kunden das Ereignis erhalten, werden die Spielergebnisse mit JavaScript im Webbrowser aktualisiert.
MySportsFeeds wird auch beim ersten Start der Node-Anwendung aufgerufen. Diese Daten werden für alle Clients verwendet, die vor dem ersten 10-Minuten-Intervall eine Verbindung herstellen. Dies wird in einer globalen Variablen gespeichert. Diese globale Variable wird im Rahmen der Intervallabfrage aktualisiert. Dadurch wird sichergestellt, dass alle neuen Clients nach dem Abruf die neuesten Daten erhalten.
Um die Code-Sauberkeit in der Hauptdatei index.js zu verbessern, habe ich eine neue Datei mit dem Namen data.js erstellt. Diese Datei enthält eine exportierte Funktion (in der Datei index.js verfügbar), die den vorherigen Aufruf der MySportsFeeds-API durchführt. Hier sind die vollständigen Inhalte dieser Datei:
var MySportsFeeds = required ("mysportsfeeds-node"); var msf = new MySportsFeeds ("1.2", true, null); msf.authenticate ("*******", "******"); var heute = neues Datum (); exports.getData = function () return msf.getData ('nhl', '2017-2018-regular', 'scoreboard', 'json', fordate: today.getFullYear () + ('0' + parseInt (heute.) .getMonth () + 1)). slice (-2) + ('0' + today.getDate ()). slice (-2), force: true); ;
EIN Daten empfangen
Die Funktion wird exportiert und gibt das Ergebnis des Aufrufs zurück. In diesem Fall handelt es sich um ein Promise, das in der Hauptanwendung aufgelöst wird.
Schauen wir uns nun den endgültigen Inhalt der Datei index.js an:
var app = requir ('express') (); var http = required ('http'). Server (App); var io = erfordern ('socket.io') (http); var data = required ('./ data.js'); // Globale Variable zum Speichern der neuesten NHL-Ergebnisse var latestData; // Lade die NHL-Daten für die erste Verbindung des Clients // Diese wird alle 10 Minuten aktualisiert. Data.getData (). Then ((Ergebnis) => latestData = Ergebnis;); app.get ('/', Funktion (req, res) res.sendFile (__ dirname + '/index.html');); http.listen (3000, function () console.log ('HTTP-Server wurde an Port 3000 gestartet');); io.on ('Verbindung', Funktion (Socket) // Wenn sich Clients verbinden, senden Sie die neuesten Daten. socket.emit ('data', latestData);); // Aktualisieren Sie data setInterval (function () data.getData (). then ((Ergebnis) => // Aktualisieren Sie die neuesten Ergebnisse für den Zeitpunkt, zu dem der neue Client eine Verbindung enthält latestData = Ergebnis; // senden Sie ihn an alle verbundenen Clients. io.emit ( 'Daten', Ergebnis); console.log ('Zuletzt aktualisiert:' + neues Datum ()););, 300000);
Die ersten sieben Codezeilen oben instanziieren die erforderlichen Bibliotheken und die globalen latestData
Variable. Die letzte Liste der verwendeten Bibliotheken sind: Express, HTTP-Server, der mit Express erstellt wurde, Socket.io und die zuvor erstellte Datei data.js, die gerade erstellt wurde.
Mit den Notwendigkeiten besetzt die Anwendung die latestData
für Clients, die eine Verbindung herstellen, wenn der Server zum ersten Mal gestartet wird:
// Globale Variable zum Speichern der neuesten NHL-Ergebnisse var latestData; // Lade die NHL-Daten für die erste Verbindung des Clients // Diese wird alle 10 Minuten aktualisiert. Data.getData (). Then ((Ergebnis) => latestData = Ergebnis;);
In den nächsten Zeilen wird eine Route für die Stammseite der Website (http: // localhost: 3000 /) eingerichtet und der HTTP-Server wird gestartet, um Port 3000 zu überwachen.
Als Nächstes wird das Socket.io eingerichtet, um nach Verbindungen zu suchen. Wenn eine neue Verbindung empfangen wird, sendet der Server ein Ereignis namens Daten mit dem Inhalt der latestData
Variable.
Und schließlich erstellt das letzte Codeabschnitt das Abrufintervall. Wenn das Intervall auftritt, wird die latestData
Variable wird mit den Ergebnissen des API-Aufrufs aktualisiert. Diese Daten senden dann dasselbe Datenereignis an alle Clients.
// Aktualisieren Sie data setInterval (function () data.getData (). then ((Ergebnis) => // Aktualisieren Sie die neuesten Ergebnisse für den Zeitpunkt, zu dem der neue Client eine Verbindung enthält latestData = Ergebnis; // senden Sie ihn an alle verbundenen Clients. io.emit ( 'Daten', Ergebnis); console.log ('Zuletzt aktualisiert:' + neues Datum ()););, 300000);
Möglicherweise stellen Sie fest, dass der Client das Ereignis mit der Socket-Variablen ausgibt, wenn der Client eine Verbindung herstellt und ein Ereignis ausgegeben wird. Bei diesem Ansatz wird das Ereignis nur an diesen verbundenen Client gesendet. Innerhalb des Intervalls der Globale io
wird verwendet, um das Ereignis auszugeben. Dadurch wird das Ereignis an alle Kunden gesendet.
Damit ist der Server fertig. Lassen Sie uns am Client-Frontend arbeiten. In einem früheren Beispiel habe ich eine einfache index.html-Datei erstellt, mit der die Clientverbindung eingerichtet wurde, die Ereignisse vom Server protokolliert und eins zurücksendet. Ich werde diese Datei um das vollständige Beispiel erweitern.
Da der Server uns ein JSON-Objekt sendet, verwende ich jQuery und nutze eine jQuery-Erweiterung namens JsRender. Dies ist eine Vorlagenbibliothek. Dadurch kann ich eine Vorlage mit HTML-Code erstellen, mit der der Inhalt jedes NHL-Spiels auf benutzerfreundliche und konsistente Weise angezeigt wird. In einem Moment werden Sie die Macht dieser Bibliothek sehen. Der letzte Code besteht aus über 40 Zeilen Code. Ich werde ihn in kleinere Abschnitte aufteilen und am Ende den vollständigen HTML-Code anzeigen.
Dieser erste Teil erstellt die Vorlage, die zur Anzeige der Spieldaten verwendet wird:
Die Vorlage wird mithilfe eines Skript-Tags definiert. Es enthält die ID der Vorlage und einen speziellen Skripttyp text / x-jsrender
. Die Vorlage definiert ein Container-Div für jedes Spiel, das ein Klassenspiel enthält, um ein einfaches Styling anzuwenden. In diesem Div beginnt das Templating.
Im nächsten Div werden die Auswärts- und Heimmannschaft angezeigt. Dies erfolgt durch Verketten von Stadt- und Teamnamen aus dem Spielobjekt aus den MySportsFeed-Daten.
: game.awayTeam.City
So definiere ich ein Objekt, das beim Rendern der Vorlage durch einen physikalischen Wert ersetzt wird. Diese Syntax wird von der JsRender-Bibliothek definiert.
Sobald die Teams angezeigt werden, führt der nächste Code etwas bedingte Logik aus. Wenn das Spiel ist nicht abgespielt
, Es wird eine Zeichenfolge ausgegeben, mit der das Spiel beginnen soll :Spielzeit
.
Wenn das Spiel nicht abgeschlossen ist, wird der aktuelle Punktestand angezeigt: Aktuelle Bewertung: : awayScore - : homeScore
. Und schließlich eine knifflige Logik, um herauszufinden, in welcher Periode sich das Hockeyspiel befindet oder ob es sich in einer Pause befindet.
Wenn die Variable aktuelleMission
steht in den Ergebnissen, dann verwende ich eine von mir definierte Funktion ordinal_suffix_of
, Dadurch wird die Periodennummer in folgende Zahl umgewandelt: 1. (2., 3. usw.) Intermission.
Wenn es nicht in Pause ist, suche ich das derzeitige Periode
Wert. Dies nutzt auch die ordinal_suffix_of
um zu zeigen, dass sich das Spiel in der 1. (2., 3. usw.) Periode befindet.
Darunter eine andere Funktion, die ich definierte übrige Zeit
wird verwendet, um die Anzahl der verbleibenden Sekunden in die Anzahl der verbleibenden Minuten und Sekunden umzuwandeln. Zum Beispiel: 10:12.
Der letzte Teil des Codes zeigt das Endergebnis an, da wir wissen, dass das Spiel abgeschlossen ist.
Hier ist ein Beispiel, wie es aussieht, wenn es eine Mischung aus fertigen Spielen, laufenden Spielen und Spielen gibt, die noch nicht begonnen haben (ich bin kein sehr guter Designer, daher sieht es so aus, als würde man von einem Entwickler erwarten ihre eigene Benutzeroberfläche).
Das nächste ist ein Stück JavaScript, das den Socket erstellt, die Helferfunktionen ordinal_suffix_of
und übrige Zeit
, und eine Variable, die auf die erstellte jQuery-Vorlage verweist.
Der letzte Code ist der Code, um das Socket-Ereignis zu empfangen und die Vorlage zu rendern:
socket.on ('data', Funktion (data) console.log (data); $ ('# data'). html (tmpl.render (data.scoreboard.gameScore, Helfer)););
Ich habe einen Platzhalter div mit der ID der Daten. Das Ergebnis der Vorlagewiedergabe (tmpl.render
) schreibt das HTML in diesen Container. Was wirklich nett ist, ist, dass die JsRender-Bibliothek in diesem Fall ein Datenarray akzeptieren kann data.scoreboard.gameScore
, Durchlaufen Sie jedes Element im Array und erstellen Sie ein Spiel pro Element.
Hier ist der endgültige HTML- und JavaScript-Code:
Socket.IO-Beispiel
Starten Sie die Anwendung Node und navigieren Sie zu http: // localhost: 3000, um die Ergebnisse für sich selbst anzuzeigen!
Alle X Minuten sendet der Server ein Ereignis an den Client. Der Client zeichnet die Spielelemente mit den aktualisierten Daten neu. Wenn Sie also die Site offen lassen und regelmäßig darauf zugreifen, werden die Spieldaten aktualisiert, wenn gerade Spiele laufen.
Das Endprodukt verwendet Socket.io, um einen Server zu erstellen, mit dem sich die Clients verbinden. Der Server holt Daten und sendet sie an den Client. Wenn der Client die Daten empfängt, kann er die Anzeige nahtlos aktualisieren. Dies verringert die Belastung des Servers, da der Client nur dann Arbeit ausführt, wenn er ein Ereignis vom Server empfängt.
Steckdosen sind nicht auf eine Richtung beschränkt; Der Client kann auch Nachrichten an den Server senden. Wenn der Server die Nachricht empfängt, kann er einige Verarbeitungsschritte ausführen.
Chat-Anwendungen funktionieren normalerweise auf diese Weise. Der Server empfängt eine Nachricht vom Client und sendet dann an alle verbundenen Clients, um anzuzeigen, dass jemand eine neue Nachricht gesendet hat.
Hoffentlich hat Ihnen dieser Artikel gefallen, da ich eine tolle Zeit hatte, diese Echtzeit-Sportanwendung für eine meiner Lieblingssportarten zu erstellen!