Advertisement
  1. Code
  2. JavaScript
  3. Node

Wie kann man eine Echtzeit-Sportanwendung mit Node.js. erstellen?

Scroll to top
Read Time: 18 min

() translation by (you can also view the original English article)

Final product imageFinal product imageFinal product image
What You'll Be Creating

In dem heutigen Artikel werde ich zeigen, wie man eine Webanwendung erstellt, die Live-Spielergebnisse aus der NHL anzeigt. Die Ergebnisse werden im Verlauf der Spiele automatisch 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:

  1. Node.js
  2. Socket.io
  3. MySportsFeed.com

Wenn Sie Node.js nicht installiert haben, besuchen Sie jetzt die Download-Seite und richten Sie sie ein, bevor Sie fortfahren.

Was ist Socket.io?

Socket.io ist eine Technologie, die einen Client mit einem Server verbindet. In diesem Beispiel ist der Client ein Webbrowser und der Server die Anwendung Node.js. Mit dem Server können gleichzeitig mehrere Clients verbunden sein.

Sobald 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, was eine bidirektionale Echtzeitkommunikation ermöglicht.

Vor Socket.io verwendeten Webanwendungen normalerweise AJAX, und sowohl der Client als auch der Server fragten sich gegenseitig nach Ereignissen ab. Beispielsweise würde alle 10 Sekunden ein AJAX-Aufruf erfolgen, um festzustellen, ob Nachrichten zu verarbeiten sind.

Das Abrufen von Nachrichten verursachte sowohl auf dem Client als auch auf dem Server einen erheblichen Overhead, da ständig nach Nachrichten gesucht wurde, wenn keine vorhanden waren.

Mit Socket.io werden Nachrichten sofort empfangen, ohne nach Nachrichten suchen zu müssen, wodurch sich der Overhead verringert.

Beispielanwendung für Socket.io

Bevor wir die Echtzeit-Sportdaten verwenden, erstellen wir eine Beispielanwendung, um zu demonstrieren, wie Socket.io funktioniert.

Zunächst werde ich eine neue Node.js-Anwendung erstellen. In einem Konsolenfenster navigiere ich zu C:\GitHub\ NodeJS, erstelle einen neuen Ordner für meine Anwendung und erstelle eine neue Anwendung:

1
cd \GitHub\NodeJS
2
mkdir SocketExample
3
cd SocketExample
4
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 an 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:

1
var app = require('express')();
2
var http = require('http').Server(app);
3
4
app.get('/', function(req, res){
5
    res.sendFile(__dirname + '/index.html');
6
});
7
8
http.listen(3000, function(){
9
	console.log('HTTP server started on port 3000');
10
});

Wenn Sie nicht mit Express vertraut sind, enthält das obige Codebeispiel die Express-Bibliothek und erstellt einen neuen HTTP-Server. In diesem Beispiel überwacht der HTTP-Server Port 3000, z. B. 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 Datei index.html erstellen, beenden wir den Server, indem wir Socket.io einrichten. Fügen Sie Ihrer Datei index.js Folgendes hinzu, um den Socket-Server zu erstellen:

1
var io = require('socket.io')(http);
2
3
io.on('connection', function(socket){
4
    console.log('Client connection received');
5
});

Ähnlich wie bei Express beginnt der Code mit dem Importieren der Socket.io-Bibliothek. Dies wird in einer Variablen namens io gespeichert. Als Nächstes wird mithilfe der Variablen io ein Ereignishandler mit der Funktion on erstellt. Das Ereignis, auf das gewartet wird, ist die Verbindung. Dieses Ereignis wird jedes Mal aufgerufen, wenn ein Client eine Verbindung zum Server herstellt.

Lassen Sie uns nun unseren sehr einfachen Client erstellen. Erstellen Sie eine neue Datei mit dem Namen index.html und fügen Sie den folgenden Code ein:

1
<!doctype html>
2
<html>
3
    <head>
4
		<title>Socket.IO Example</title>
5
	</head>
6
	<body>
7
		<script src="/socket.io/socket.io.js"></script>
8
		<script>
9
			var socket = io();
10
		</script>
11
	</body>
12
</html>

Der obige HTML-Code lädt das JavaScript des Socket.io-Clients und initialisiert eine Verbindung zum Server. Um das Beispiel anzuzeigen, starten Sie Ihre Knotenanwendung: node index.js

Navigieren Sie dann in Ihrem Browser zu http://localhost:3000. Auf der Seite wird nichts angezeigt. Wenn Sie sich jedoch die Konsole ansehen, auf der die Knotenanwendung ausgeführt wird, werden zwei Nachrichten protokolliert:

  1. Der HTTP-Server wurde an Port 3000 gestartet
  2. Client-Verbindung empfangen

Nachdem wir eine erfolgreiche Socket-Verbindung haben, können wir sie verwenden. Beginnen wir mit dem Senden einer Nachricht vom Server an den Client. Wenn der Client die Nachricht empfängt, kann er eine Antwort an den Server zurücksenden.

Schauen wir uns die abgekürzte Datei index.js an:

1
io.on('connection', function(socket){
2
    console.log('Client connection received');
3
	
4
	socket.emit('sendToClient', { hello: 'world' });
5
	
6
	socket.on('receivedFromClient', function (data) {
7
		console.log(data);
8
	});
9
});

Die vorherige io.on-Funktion wurde aktualisiert und enthält nun einige neue Codezeilen. Der erste, socket.emit, sendet die Nachricht an den Client. Der sendToClient ist der Name des Ereignisses. Durch Benennen von Ereignissen können Sie verschiedene Arten von Nachrichten senden, damit der Client sie unterschiedlich interpretieren kann. Die zweite Ergänzung ist die Datei socket.on, die auch einen Ereignisnamen 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 aktualisieren, um das sendToClient-Ereignis zu empfangen. Wenn es das Ereignis empfängt, kann es mit dem receivedFromClient-Ereignis auf den Server zurück antworten.

Dies wird im JavaScript-Teil des HTML-Codes erreicht. In der Datei index.html habe ich das JavaScript also wie folgt aktualisiert:

1
var socket = io();
2
3
socket.on('sendToClient', function (data) {
4
    console.log(data);
5
	
6
	socket.emit('receivedFromClient', { my: 'data' });
7
});

Unter Verwendung der instanziierten Socket-Variablen haben wir auf dem Server eine sehr ähnliche Logik mit einer socket.on-Funktion. Für den Client hört er das sendToClient-Ereignis ab. Sobald der Client verbunden ist, sendet der Server diese Nachricht. Wenn der Client es empfängt, wird es im Browser an der Konsole protokolliert. Der Client verwendet dann dasselbe socket.emit, mit dem der Server das ursprüngliche Ereignis gesendet hat. In diesem Fall sendet der Client das Ereignis receiveFromClient an den Server zurück. Wenn der Server die Nachricht empfängt, wird sie im Konsolenfenster protokolliert.

Probieren Sie es aus. Führen Sie zunächst in einer Konsole Ihre Knotenanwendung aus: node index.js. Laden Sie dann http://localhost:3000 in Ihren Browser.

Überprüfen Sie die Webbrowser-Konsole und Sie sollten die folgenden protokollierten JSON-Daten sehen: {hello: "world"}

In der Eingabeaufforderung, in der die Knotenanwendung ausgeführt wird, sollte Folgendes angezeigt werden:

1
HTTP server started on port 3000
2
Client connection received
3
{ my: 'data' }

Sowohl der Client als auch der Server können die empfangenen JSON-Daten verwenden, um bestimmte Aufgaben auszuführen. Wir werden mehr darüber erfahren, sobald wir uns mit den Echtzeit-Sportdaten verbinden.

Sportdaten

Nachdem wir das Senden und Empfangen von Daten zum und vom Client und Server beherrschen, kann dies genutzt werden, um Echtzeit-Updates bereitzustellen. Ich habe mich für Sportdaten entschieden, obwohl die gleiche Theorie nicht auf Sport beschränkt ist. Bevor ich mit diesem Projekt anfing, habe ich verschiedene Sportdaten recherchiert. Die, für die ich mich entschieden habe, weil sie kostenlose Entwicklerkonten anbieten, war MySportsFeeds (ich bin in keiner Weise mit ihnen verbunden). Um auf die Echtzeitdaten zuzugreifen, habe ich mich für ein Konto angemeldet und dann eine kleine Spende geleistet. Spenden beginnen bei 1 US-Dollar, damit die Daten alle 10 Minuten aktualisiert werden. Dies ist gut für das Beispiel.

Sobald Ihr Konto eingerichtet ist, können Sie mit dem Einrichten des Zugriffs auf die API fortfahren. Um dies zu unterstützen, werde ich das NPM-Paket verwenden: npm install mysportsfeeds-node --save

Nach der Installation des Pakets können API-Aufrufe wie folgt ausgeführt werden:

1
var MySportsFeeds = require("mysportsfeeds-node");
2
3
var msf = new MySportsFeeds("1.2", true);
4
msf.authenticate("********", "*********");
5
6
var today = new Date();
7
8
msf.getData('nhl', '2017-2018-regular', 'scoreboard', 'json', { 
9
    fordate: today.getFullYear() + 
10
		('0' + parseInt(today.getMonth() + 1)).slice(-2) + 
11
		('0' + today.getDate()).slice(-2),
12
	force: true
13
});

Stellen Sie im obigen Beispiel sicher, dass Sie 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. Die fordate-Variable gibt heute an. Ich habe außerdem force auf true gesetzt, damit 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 namens game. Dieses Objekt enthält Informationen darüber, wer spielt.

Außerhalb des Spielobjekts gibt es eine Handvoll Variablen, die den aktuellen Status des Spiels anzeigen. Die Daten ändern sich je nach Spielstatus. Wenn das Spiel beispielsweise noch nicht gestartet wurde, gibt es nur wenige Variablen, die uns mitteilen, dass das Spiel nicht ausgeführt wird und noch nicht gestartet wurde.

Während des Spiels werden zusätzliche Daten über die Punktzahl, den Zeitraum des Spiels und die verbleibende Zeit bereitgestellt. Wir werden dies in Aktion sehen, wenn wir zum HTML gelangen, um das Spiel im nächsten Abschnitt zu zeigen.

Echtzeit-Updates

Wir haben alle Teile des Puzzles, also ist es jetzt an der Zeit, das Puzzle zusammenzusetzen, um das endgültige Bild zu enthüllen. Derzeit unterstützt MySportsFeeds nur begrenzt Daten an uns, sodass wir die Daten von ihnen abfragen müssen. Glücklicherweise wissen wir, dass sich die Daten nur einmal alle 10 Minuten ändern, sodass wir keinen zusätzlichen Aufwand verursachen müssen, indem wir zu häufig nach Änderungen suchen. Sobald wir die Daten von ihnen abgefragt haben, können wir diese Updates vom Server an alle verbundenen Clients senden.

Um die Abfrage durchzuführen, werde ich die JavaScript-Funktion setInterval verwenden, 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 im Webbrowser mit JavaScript aktualisiert.

MySportsFeeds wird auch beim ersten Start der Knotenanwendung 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. Dieselbe globale Variable wird im Rahmen der Intervallabfrage aktualisiert. Dadurch wird sichergestellt, dass neue Clients, die nach der Abfrage eine Verbindung herstellen, über die neuesten Daten verfügen.

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 (verfügbar in der Datei index.js), die den vorherigen Aufruf der MySportsFeeds-API ausführt. Hier ist der vollständige Inhalt dieser Datei:

1
var MySportsFeeds = require("mysportsfeeds-node");
2
3
var msf = new MySportsFeeds("1.2", true, null);
4
msf.authenticate("*******", "******");
5
6
var today = new Date();
7
8
exports.getData = function() {
9
10
    	return msf.getData('nhl', '2017-2018-regular', 'scoreboard', 'json', { 
11
		fordate: today.getFullYear() + 
12
			('0' + parseInt(today.getMonth() + 1)).slice(-2) + 
13
			('0' + today.getDate()).slice(-2),
14
		force: true
15
		});
16
17
};

Eine getData-Funktion wird exportiert und gibt das Ergebnis des Aufrufs zurück. In diesem Fall handelt es sich um ein Versprechen, das in der Hauptanwendung aufgelöst wird.

Schauen wir uns nun den endgültigen Inhalt der Datei index.js an:

1
var app = require('express')();
2
var http = require('http').Server(app);
3
var io = require('socket.io')(http);
4
var data = require('./data.js');
5
6
// Global variable to store the latest NHL results

7
var latestData;
8
9
// Load the NHL data for when client's first connect

10
// This will be updated every 10 minutes

11
data.getData().then((result) => { 
12
    latestData = result;
13
});
14
15
app.get('/', function(req, res){
16
	res.sendFile(__dirname + '/index.html');
17
});
18
19
http.listen(3000, function(){
20
	console.log('HTTP server started on port 3000');
21
});
22
23
io.on('connection', function(socket){
24
	// when clients connect, send the latest data

25
	socket.emit('data', latestData);
26
});
27
28
// refresh data

29
setInterval(function() {
30
	data.getData().then((result) => { 
31
		// Update latest results for when new client's connect

32
		latestData = result; 
33
	
34
		// send it to all connected clients

35
		io.emit('data', result);
36
		
37
		console.log('Last updated: ' + new Date());
38
	});
39
}, 300000);

Die ersten sieben Codezeilen oben instanziieren die erforderlichen Bibliotheken und die globale Variable latestData. Die endgültige Liste der verwendeten Bibliotheken lautet: Express, mit Express erstellter HTTP-Server, Socket.io und die oben erstellte Datei data.js.

Nachdem die erforderlichen Vorkehrungen getroffen wurden, füllt die Anwendung die latestData für Clients, die beim ersten Start des Servers eine Verbindung herstellen:

1
// Global variable to store the latest NHL results

2
var latestData;
3
4
// Load the NHL data for when client's first connect

5
// This will be updated every 10 minutes

6
data.getData().then((result) => { 
7
    latestData = result;
8
});

In den nächsten Zeilen wird eine Route für die Stammseite der Website (http://localhost:3000/) eingerichtet und der HTTP-Server gestartet, um Port 3000 abzuhören.

Als nächstes wird Socket.io eingerichtet, um nach Verbindungen zu suchen. Wenn eine neue Verbindung empfangen wird, sendet der Server ein Ereignis namens data mit dem Inhalt der Variablen latestData aus.

Und schließlich erstellt der letzte Codeabschnitt das Abfrageintervall. Wenn das Intervall auftritt, wird die Variable latestData mit den Ergebnissen des API-Aufrufs aktualisiert. Diese Daten senden dann das gleiche Datenereignis an alle Clients.

1
// refresh data

2
setInterval(function() {
3
    data.getData().then((result) => { 
4
		// Update latest results for when new client's connect

5
		latestData = result; 
6
	
7
		// send it to all connected clients

8
		io.emit('data', result);
9
		
10
		console.log('Last updated: ' + new Date());
11
	});
12
}, 300000);

Möglicherweise stellen Sie fest, dass der Client beim Herstellen einer Verbindung und beim Ausgeben eines Ereignisses das Ereignis mit der Socket-Variablen ausgibt. Dieser Ansatz sendet das Ereignis nur an diesen verbundenen Client. Innerhalb des Intervalls wird das globale io verwendet, um das Ereignis auszusenden. Dadurch wird das Ereignis an alle Clients gesendet.

Damit ist der Server fertig. Lassen Sie uns am Client-Frontend arbeiten. In einem früheren Beispiel habe ich eine grundlegende index.html-Datei erstellt, in der die Clientverbindung eingerichtet wurde, mit der Ereignisse vom Server protokolliert und zurückgesendet werden. Ich werde diese Datei erweitern, um das fertige Beispiel zu enthalten.

Da der Server uns ein JSON-Objekt sendet, werde ich jQuery verwenden und eine jQuery-Erweiterung namens JsRender nutzen. Dies ist eine Vorlagenbibliothek. Dadurch kann ich eine Vorlage mit HTML erstellen, mit der der Inhalt jedes NHL-Spiels auf benutzerfreundliche und konsistente Weise angezeigt wird. Gleich sehen Sie die Leistungsfähigkeit dieser Bibliothek. Der endgültige Code besteht aus mehr als 40 Codezeilen, daher werde ich ihn in kleinere Teile aufteilen und am Ende den vollständigen HTML-Code zusammen anzeigen.

In diesem ersten Teil wird die Vorlage erstellt, mit der die Spieldaten angezeigt werden:

1
<script id="gameTemplate" type="text/x-jsrender">
2
<div class="game">
3
    <div>
4
		{{:game.awayTeam.City}} {{:game.awayTeam.Name}} at {{:game.homeTeam.City}} {{:game.homeTeam.Name}}
5
	</div>

6
	<div>
7
		{{if isUnplayed == "true" }}
8
		
9
		Game starts at {{:game.time}}
10
		
11
		{{else isCompleted == "false"}}
12
		
13
		<div>Current Score: {{:awayScore}} - {{:homeScore}}</div>

14
		
15
		<div>
16
			{{if currentIntermission}}
17
				{{:~ordinal_suffix_of(currentIntermission)}} Intermission
18
			{{else currentPeriod}}
19
				{{:~ordinal_suffix_of(currentPeriod)}}<br/>
20
				{{:~time_left(currentPeriodSecondsRemaining)}}
21
			{{else}}
22
				1st
23
			{{/if}}
24
		</div>

25
		
26
		{{else}}
27
		
28
		Final Score: {{:awayScore}} - {{:homeScore}}
29
		
30
		{{/if}}
31
	</div>

32
</div>

33
</script>

Die Vorlage wird mithilfe eines Skript-Tags definiert. Es enthält die ID der Vorlage und einen speziellen Skripttyp namens text/x-jsrender. Die Vorlage definiert ein Container-Div für jedes Spiel, das ein Klassenspiel enthält, um ein grundlegendes Styling anzuwenden. In diesem Div beginnt das Templating.

In der nächsten Division werden die Auswärts- und Heimmannschaft angezeigt. Dies erfolgt durch Verketten des Stadt- und Teamnamens aus dem Spielobjekt aus den MySportsFeed-Daten.

Mit {{:game.awayTeam.City}} definiere ich ein Objekt, das beim Rendern der Vorlage durch einen physischen Wert ersetzt wird. Diese Syntax wird von der JsRender-Bibliothek definiert.

Sobald die Teams angezeigt werden, führt der nächste Codeabschnitt eine bedingte Logik aus. Wenn das Spiel unPlayed ist, wird ein String ausgegeben, dass das Spiel um {{:game.time}} beginnt.

Wenn das Spiel nicht beendet ist, wird die aktuelle Punktzahl angezeigt: Current Score: {{:awayScore}} - {{:homeScore}}. Und schließlich eine knifflige kleine Logik, um festzustellen, in welcher Zeit sich das Hockeyspiel befindet oder ob es sich in einer Pause befindet.

Wenn die Variable currentIntermission in den Ergebnissen angegeben ist, verwende ich eine von mir definierte Funktion namens ordinal_suffix_of, die die Periodennummer in Folgendes umwandelt: 1. (2., 3. usw.) Pause.

Wenn es nicht in der Pause ist, suche ich nach dem currentPeriod-Wert. Dies verwendet auch das ordinal_suffix_of, um anzuzeigen, dass sich das Spiel in der 1. (2., 3. usw.) Periode befindet.

Darunter wird eine andere von mir definierte Funktion namens time_left verwendet, um die Anzahl der verbleibenden Sekunden in die Anzahl der verbleibenden Minuten und Sekunden in der Periode 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 dafür, wie es aussieht, wenn es eine Mischung aus fertigen Spielen, laufenden Spielen und Spielen gibt, die noch nicht gestartet wurden (ich bin kein sehr guter Designer, also sieht es so aus, wie Sie es von einem Entwickler erwarten würden ihre eigene Benutzeroberfläche).

An example of finished gamesAn example of finished gamesAn example of finished games

Als nächstes folgt ein Teil von JavaScript, der den Socket erstellt, die Hilfsfunktionen ordinal_suffix_of und time_left sowie eine Variable, die auf die erstellte jQuery-Vorlage verweist.

1
<script>
2
    var socket = io();
3
	var tmpl = $.templates("#gameTemplate");
4
	
5
	var helpers = {
6
		ordinal_suffix_of: function(i) {
7
			var j = i % 10,
8
			k = i % 100;
9
			if (j == 1 && k != 11) {
10
				return i + "st";
11
			}
12
			if (j == 2 && k != 12) {
13
				return i + "nd";
14
			}
15
			if (j == 3 && k != 13) {
16
				return i + "rd";
17
			}
18
			return i + "th";
19
		},
20
		time_left: function(time) {
21
			var minutes = Math.floor(time / 60);
22
			var seconds = time - minutes * 60;
23
			
24
			return minutes + ':' + ('0' + seconds).slice(-2);
25
		}
26
	};
27
</script>

Der letzte Code ist der Code zum Empfangen des Socket-Ereignisses und zum Rendern der Vorlage:

1
socket.on('data', function (data) {
2
    console.log(data);
3
	
4
	$('#data').html(tmpl.render(data.scoreboard.gameScore, helpers));
5
});

Ich habe einen Platzhalter div mit der ID der Daten. Das Ergebnis des Template-Renderings (tmpl.render) schreibt den HTML-Code in diesen Container. Was wirklich toll ist, ist, dass die JsRender-Bibliothek ein Array von Daten akzeptieren kann, in diesem Fall data.scoreboard.gameScore, das jedes Element im Array durchläuft und ein Spiel pro Element erstellt.

Hier ist das endgültige HTML und JavaScript zusammen:

1
<!doctype html>
2
<html>
3
    <head>
4
		<title>Socket.IO Example</title>
5
	</head>
6
	<body>
7
		<div id="data">
8
		
9
		</div>
10
	
11
<script id="gameTemplate" type="text/x-jsrender">
12
<div class="game">
13
	<div>
14
		{{:game.awayTeam.City}} {{:game.awayTeam.Name}} at {{:game.homeTeam.City}} {{:game.homeTeam.Name}}
15
	</div>

16
	<div>
17
		{{if isUnplayed == "true" }}
18
		
19
		Game starts at {{:game.time}}
20
		
21
		{{else isCompleted == "false"}}
22
		
23
		<div>Current Score: {{:awayScore}} - {{:homeScore}}</div>

24
		
25
		<div>
26
			{{if currentIntermission}}
27
				{{:~ordinal_suffix_of(currentIntermission)}} Intermission
28
			{{else currentPeriod}}
29
				{{:~ordinal_suffix_of(currentPeriod)}}<br/>
30
				{{:~time_left(currentPeriodSecondsRemaining)}}
31
			{{else}}
32
				1st
33
			{{/if}}
34
		</div>

35
		
36
		{{else}}
37
		
38
		Final Score: {{:awayScore}} - {{:homeScore}}
39
		
40
		{{/if}}
41
	</div>

42
</div>

43
</script>
44
	
45
		<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
46
		<script src="https://cdnjs.cloudflare.com/ajax/libs/jsrender/0.9.90/jsrender.min.js"></script>
47
		<script src="/socket.io/socket.io.js"></script>
48
		<script>
49
			var socket = io();
50
			
51
			var helpers = {
52
				ordinal_suffix_of: function(i) {
53
					var j = i % 10,
54
					k = i % 100;
55
					if (j == 1 && k != 11) {
56
						return i + "st";
57
					}
58
					if (j == 2 && k != 12) {
59
						return i + "nd";
60
					}
61
					if (j == 3 && k != 13) {
62
						return i + "rd";
63
					}
64
					return i + "th";
65
				},
66
				time_left: function(time) {
67
					var minutes = Math.floor(time / 60);
68
					var seconds = time - minutes * 60;
69
					
70
					return minutes + ':' + ('0' + seconds).slice(-2);
71
				}
72
			};
73
			
74
			var tmpl = $.templates("#gameTemplate");
75
			
76
			socket.on('data', function (data) {
77
				console.log(data);
78
				
79
				$('#data').html(tmpl.render(data.scoreboard.gameScore, helpers));
80
			});
81
		</script>
82
		
83
		<style>
84
		.game {
85
			border: 1px solid #000;
86
			float: left;
87
			margin: 1%;
88
			padding: 1em;
89
			width: 25%;
90
		}
91
		</style>
92
	</body>
93
</html>

Starten Sie die Node-Anwendung und navigieren Sie zu http://localhost:3000, um die Ergebnisse selbst zu sehen!

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 Website geöffnet lassen und sie regelmäßig ansehen, werden die Spieldaten aktualisiert, wenn Spiele gerade ausgeführt werden.

Abschluss

Das Endprodukt verwendet Socket.io, um einen Server zu erstellen, mit dem Clients eine Verbindung herstellen. Der Server ruft Daten ab und sendet sie an den Client. Wenn der Client die Daten empfängt, kann er die Anzeige nahtlos aktualisieren. Dies reduziert 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 eine Verarbeitung durchführen.

Chat-Anwendungen funktionieren normalerweise so. Der Server empfängt eine Nachricht vom Client und sendet sie dann an alle verbundenen Clients, um anzuzeigen, dass jemand eine neue Nachricht gesendet hat.

Hoffentlich hat Ihnen dieser Artikel gefallen, denn ich hatte viel Spaß beim Erstellen dieser Echtzeit-Sportanwendung für eine meiner Lieblingssportarten!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.