Comment créer une application de sport en temps réel à l'aide de Node.js

Ce que vous allez créer

Dans l'article d'aujourd'hui, je vais vous montrer comment créer une application Web permettant d'afficher les scores en direct de la LNH. Les scores seront automatiquement mis à jour au fur et à mesure de l'avancement des jeux.

C'est un article très excitant pour moi, car il me permet de réunir deux de mes passions préférées: le développement et le sport..

Les technologies qui seront utilisées pour créer l'application sont:

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

Si vous n'avez pas installé Node.js, visitez leur page de téléchargement maintenant et configurez-le avant de continuer.

Qu'est-ce que Socket.io?

Socket.io est une technologie qui connecte un client à un serveur. Dans cet exemple, le client est un navigateur Web et le serveur est l'application Node.js. Le serveur peut avoir plusieurs clients connectés à tout moment..

Une fois la connexion établie, le serveur peut envoyer des messages à tous les clients ou à un client individuel. En retour, le client peut envoyer un message au serveur, permettant une communication bidirectionnelle en temps réel..

Avant Socket.io, les applications Web utilisaient généralement AJAX, et le client et le serveur s'interrogeaient mutuellement à la recherche d'événements. Par exemple, toutes les 10 secondes, un appel AJAX se produirait pour voir s’il y avait des messages à gérer..

La scrutation des messages entraînait une surcharge importante à la fois pour le client et pour le serveur, car il était constamment à la recherche de messages alors qu’il n’y en avait pas..

Avec Socket.io, les messages sont reçus instantanément, sans avoir besoin de chercher des messages, ce qui réduit le temps système.

Exemple d'application Socket.io

Avant de consommer les données sportives en temps réel, créons un exemple d'application illustrant le fonctionnement de Socket.io..

Pour commencer, je vais créer une nouvelle application Node.js. Dans une fenêtre de console, je vais accéder à C: \ GitHub \ NodeJS, créer un nouveau dossier pour mon application et créer une nouvelle application:

cd \ GitHub \ NodeJS mkdir SocketExample cd SocketExample npm init

J'ai utilisé tous les paramètres par défaut.

Comme nous créons une application Web, je vais utiliser un package NPM appelé Express pour simplifier la configuration. Dans une invite de commande, installez-le comme suit: npm install express --save

Et bien sûr, nous devrons installer le package Socket.io: npm install socket.io --save

Commençons par créer le serveur Web. Créez un nouveau fichier appelé index.js et placez-y le code suivant pour créer le serveur Web à l'aide d'Express:

var app = require ('express') (); var http = require ('http'). Server (app); app.get ('/', fonction (req, res) res.sendFile (__ dirname + '/index.html');); http.listen (3000, function () console.log ('Le serveur HTTP a démarré sur le port 3000'););

Si vous ne connaissez pas Express, l'exemple de code ci-dessus inclut la bibliothèque Express et crée un nouveau serveur HTTP. Dans cet exemple, le serveur HTTP écoute sur le port 3000, par exemple. http: // localhost: 3000. Un itinéraire est créé à la racine du site "/". Le résultat de la route retourne un fichier HTML: index.html.

Avant de créer le fichier index.html, finissons le serveur en configurant Socket.io. Ajoutez les éléments suivants à votre fichier index.js pour créer le serveur Socket:

var io = require ('socket.io') (http); io.on ('connexion', fonction (socket) console.log ('connexion client reçue'););

Semblable à Express, le code commence par importer la bibliothèque Socket.io. Ceci est stocké dans une variable appelée io. Ensuite, en utilisant le io variable, un gestionnaire d’événements est créé avec le sur une fonction. L'événement en cours d'écoute est sa connexion. Cet événement est appelé chaque fois qu'un client se connecte au serveur..

Créons maintenant notre client très basique. Créez un nouveau fichier appelé index.html et insérez le code suivant dans:

   Exemple Socket.IO      

Le code HTML ci-dessus charge le code JavaScript du client Socket.io et initialise une connexion au serveur. Pour voir l'exemple, démarrez votre application Node: noeud index.js

Ensuite, dans votre navigateur, accédez à http: // localhost: 3000. Rien n'apparaîtra sur la page. Cependant, si vous regardez la console où l'application Node est en cours d'exécution, deux messages sont consignés:

  1. Le serveur HTTP a démarré sur le port 3000
  2. Connexion client reçue

Maintenant que nous avons une connexion socket réussie, mettons-la à utiliser. Commençons par envoyer un message du serveur au client. Ensuite, lorsque le client reçoit le message, il peut renvoyer une réponse au serveur..

Regardons le fichier index.js abrégé:

io.on ('connexion', fonction (socket) console.log ('connexion client reçue'); socket.emit ('sendToClient', hello: 'world'); socket.on ('receiveFromClient', fonction (data) console.log (data);););

La précédente io.on La fonction a été mise à jour pour inclure quelques nouvelles lignes de code. La première, socket.emit, envoie le message au client. le sendToClient est le nom de l'événement. En nommant des événements, vous pouvez envoyer différents types de messages afin que le client puisse les interpréter différemment. Le deuxième ajout est le socket.on, qui contient également un nom d'événement: reçuDeClient. Cela crée une fonction qui accepte les données du client. Dans ce cas, les données sont enregistrées dans la fenêtre de la console..

Cela complète les modifications côté serveur; il peut maintenant envoyer et recevoir des données de tous les clients connectés.

Terminons cet exemple en mettant à jour le client pour qu'il reçoive le message. sendToClient un événement. Quand il reçoit l'événement, il peut répondre avec le message reçuDeClient événement sur le serveur.

Ceci est accompli dans la partie JavaScript du code HTML, donc dans le fichier index.html, j'ai mis à jour le code JavaScript comme suit:

var socket = io (); socket.on ('sendToClient', fonction (données) console.log (données); socket.emit ('receiveFromClient', my: 'données'););

En utilisant la variable socket instanciée, nous avons une logique très similaire sur le serveur avec un socket.on une fonction. Pour le client, il écoute les sendToClient un événement. Dès que le client est connecté, le serveur envoie ce message. Lorsque le client le reçoit, il est connecté à la console dans le navigateur. Le client utilise ensuite le même socket.emit que le serveur utilisait pour envoyer l'événement d'origine. Dans ce cas, le client renvoie le message. reçuDeClient événement sur le serveur. Lorsque le serveur reçoit le message, il est enregistré dans la fenêtre de la console..

Essayez vous-même. Tout d'abord, dans une console, exécutez votre application Node: noeud index.js. Puis chargez http: // localhost: 3000 dans votre navigateur.

Vérifiez la console du navigateur Web et vous devriez voir les données JSON suivantes consignées: Bonjour le monde"

Ensuite, dans l'invite de commande où l'application Node est en cours d'exécution, vous devriez voir ce qui suit:

Le serveur HTTP a démarré sur le port 3000 La connexion du client a été reçue my: 'data'

Le client et le serveur peuvent utiliser les données JSON reçues pour effectuer des tâches spécifiques. Nous en apprendrons plus à ce sujet une fois que nous serons connectés aux données sportives en temps réel.

Données sportives

Maintenant que nous savons comment envoyer et recevoir des données vers et depuis le client et le serveur, nous pouvons en tirer parti pour fournir des mises à jour en temps réel. J'ai choisi d'utiliser des données sportives, bien que la même théorie ne se limite pas au sport. Avant de commencer ce projet, j'ai effectué des recherches sur différentes données sportives. Le site sur lequel j’ai opté, parce qu’ils offrent des comptes de développeur gratuits, est MySportsFeeds (je ne suis aucunement affilié à eux). Pour accéder aux données en temps réel, j'ai ouvert un compte puis effectué un petit don. Les dons commencent à 1 $ pour que les données soient mises à jour toutes les 10 minutes. Ce sera bon pour l'exemple.

Une fois votre compte configuré, vous pouvez configurer l'accès à leur API. Pour vous aider, je vais utiliser leur package NPM: npm installe mysportsfeeds-node --save

Une fois le package installé, les appels d'API peuvent être effectués comme suit:

var MySportsFeeds = require ("mysportsfeeds-node"); var msf = new MySportsFeeds ("1.2", true); msf.authenticate ("********", "*********"); var today = new Date (); msf.getData ('nhl', '2017-2018-regular', 'tableau d'affichage', 'json', fordate: today.getFullYear () + ('0' + parseInt (today.getMonth () + 1)). slice (-2) + ('0' + today.getDate ()). slice (-2), force: true);

Dans l'exemple ci-dessus, veillez à remplacer l'appel à la fonction d'authentification par votre nom d'utilisateur et votre mot de passe..

Le code suivant exécute un appel d'API pour obtenir le tableau de bord de la LNH pour aujourd'hui. le gué variable est ce qui spécifie aujourd'hui. J'ai aussi mis Obliger à vrai de sorte qu'une réponse est toujours renvoyée, même lorsque les données n'ont pas changé.

Avec la configuration actuelle, les résultats de l'appel de l'API sont écrits dans un fichier texte. Dans le dernier exemple, cela sera changé. toutefois, à des fins de démonstration, le fichier de résultats peut être examiné dans un éditeur de texte afin de comprendre le contenu de la réponse. Les résultats contiennent un objet de tableau de bord. Cet objet contient un tableau appelé gameScore. Cet objet stocke le résultat de chaque match. Chaque objet contient un objet enfant appelé Jeu. Cet objet fournit des informations sur qui joue.

En dehors de l'objet de jeu, il existe une poignée de variables qui fournissent l'état actuel du jeu. Les données changent en fonction de l'état du jeu. Par exemple, lorsque le jeu n'a pas démarré, seules quelques variables nous indiquent que le jeu n'est pas en cours et qu'il n'a pas encore commencé..

Lorsque le jeu est en cours, des données supplémentaires sont fournies sur le score, la période de jeu et le temps restant. Nous verrons cela en action lorsque nous arriverons au HTML pour montrer le jeu dans la section suivante.

Mises à jour en temps réel

Nous avons toutes les pièces du puzzle, il est donc temps de les assembler pour révéler la photo finale. Actuellement, MySportsFeeds a un support limité pour nous envoyer des données, nous devrons donc les interroger. Heureusement, nous savons que les données ne changent qu'une fois toutes les 10 minutes. Nous n'avons donc pas besoin d'ajouter de temps supplémentaire en interrogeant les modifications trop fréquemment. Une fois que nous avons interrogé leurs données, nous pouvons transmettre ces mises à jour du serveur à tous les clients connectés..

Pour effectuer le sondage, je vais utiliser le JavaScript setInterval fonction pour appeler l'API (dans mon cas) toutes les 10 minutes pour rechercher des mises à jour. Lorsque les données sont reçues, un événement est envoyé à tous les clients connectés. Lorsque les clients reçoivent l'événement, les scores du jeu seront mis à jour avec JavaScript dans le navigateur Web..

MySportsFeeds sera également appelé lors du premier démarrage de l'application Node. Ces données seront utilisées pour tous les clients qui se connectent avant le premier intervalle de 10 minutes. Ceci est stocké dans une variable globale. Cette même variable globale est mise à jour dans le cadre de l'interrogation par intervalle. Cela garantira que lorsque de nouveaux clients se connecteront après l’interrogation, ils disposeront des données les plus récentes..

Pour vous aider avec une certaine propreté du code dans le fichier principal index.js, j'ai créé un nouveau fichier appelé data.js. Ce fichier contiendra une fonction exportée (disponible dans le fichier index.js) qui effectue l'appel précédent à l'API MySportsFeeds. Voici le contenu complet de ce fichier:

var MySportsFeeds = require ("mysportsfeeds-node"); var msf = new MySportsFeeds ("1.2", true, null); msf.authenticate ("*******", "******"); var today = new Date (); exports.getData = function () return msf.getData ('nhl', '2017-2018-regular', 'tableau d'affichage', 'json', fordate: today.getFullYear () + ('0' + parseInt (aujourd'hui .getMonth () + 1)). slice (-2) + ('0' + aujourd'hui.getDate ()). slice (-2), force: true); ;

UNE getData la fonction est exportée et renvoie le résultat de l'appel, qui est dans ce cas une promesse qui sera résolue dans l'application principale.

Regardons maintenant le contenu final du fichier index.js:

var app = require ('express') (); var http = require ('http'). Server (app); var io = require ('socket.io') (http); var data = require ('./ data.js'); // Variable globale pour stocker les derniers résultats de la LNH var latestData; // Charge les données NHL pour la première connexion du client // Ceci sera mis à jour toutes les 10 minutes data.getData (). Then ((result) => latestData = result;); app.get ('/', fonction (req, res) res.sendFile (__ dirname + '/index.html');); http.listen (3000, function () console.log ('Le serveur HTTP a démarré sur le port 3000');); io.on ('connexion', fonction (socket) // lors de la connexion des clients, envoie le dernier socket de données.emit ('data', latestData);); // actualise les données setInterval (function () data.getData (). then ((result)) => // // Met à jour les derniers résultats lorsque le nouveau client se connecte lastData = result; // l'envoie à tous les clients connectés io.emit ( 'data', result); console.log ('Dernière mise à jour:' + nouvelle date ()););, 300000);

Les sept premières lignes de code ci-dessus instancient les bibliothèques requises et le fichier global. dernierDonnées variable. La liste finale des bibliothèques utilisées est la suivante: Express, serveur HTTP créé avec Express, Socket.io et le fichier data.js susmentionné qui vient d'être créé..

Avec les nécessités prises en charge, l'application remplit le dernierDonnées pour les clients qui se connecteront au démarrage du serveur:

// Variable globale pour stocker les derniers résultats de la LNH var latestData; // Charge les données NHL pour la première connexion du client // Ceci sera mis à jour toutes les 10 minutes data.getData (). Then ((result) => latestData = result;);

Les lignes suivantes définissent un itinéraire pour la page racine du site Web (http: // localhost: 3000 /) et démarrent le serveur HTTP pour écouter sur le port 3000..

Ensuite, le Socket.io est configuré pour rechercher des connexions. Lors de la réception d’une nouvelle connexion, le serveur émet un événement appelé data avec le contenu de la dernierDonnées variable.

Et enfin, le dernier bloc de code crée l'intervalle d'interrogation. Lorsque l'intervalle se produit, le dernierDonnées La variable est mise à jour avec les résultats de l'appel de l'API. Ces données émettent ensuite le même événement de données à tous les clients..

// actualise les données setInterval (function () data.getData (). then ((result)) => // // Met à jour les derniers résultats lorsque le nouveau client se connecte lastData = result; // l'envoie à tous les clients connectés io.emit ( 'data', result); console.log ('Dernière mise à jour:' + nouvelle date ()););, 300000);

Vous remarquerez peut-être que lorsque le client se connecte et qu'un événement est émis, il émet l'événement avec la variable socket. Cette approche enverra l'événement à ce client connecté uniquement. À l'intérieur de l'intervalle, le global io est utilisé pour émettre l'événement. Cela enverra l'événement à tous les clients..

Cela complète le serveur. Travaillons sur le front-end du client. Dans un exemple précédent, j'avais créé un fichier index.html de base qui configurait la connexion cliente qui consignait les événements du serveur et en renvoyait un. Je vais étendre ce fichier pour contenir l'exemple complet.

Comme le serveur nous envoie un objet JSON, je vais utiliser jQuery et exploiter une extension jQuery appelée JsRender. Ceci est une bibliothèque de modèles. Cela me permettra de créer un modèle HTML qui sera utilisé pour afficher le contenu de chaque match de la LNH de manière cohérente et facile à utiliser. Dans un instant, vous verrez le pouvoir de cette bibliothèque. Le code final compte plus de 40 lignes de code, je vais donc le décomposer en morceaux plus petits, puis afficher le code HTML complet ensemble à la fin..

Cette première partie crée le modèle qui sera utilisé pour afficher les données du jeu:

Le modèle est défini à l'aide d'une balise de script. Il contient l'identifiant du modèle et un type de script spécial appelé text / x-jsrender. Le modèle définit une division conteneur pour chaque jeu contenant un jeu de classe auquel appliquer un style de base. À l'intérieur de cette div, le templating commence.

Dans la division suivante, l'équipe à domicile et à domicile est affichée. Ceci est fait en concaténant la ville et le nom de l'équipe ensemble à partir de l'objet de jeu à partir des données MySportsFeed.

: game.awayTeam.City Voici comment je définis un objet qui sera remplacé par une valeur physique lors du rendu du modèle. Cette syntaxe est définie par la bibliothèque JsRender..

Une fois que les équipes sont affichées, le bloc de code suivant exécute une logique conditionnelle. Quand le jeu est non joué, une chaîne sera générée pour que le jeu commence à :temps de jeu.

Lorsque le jeu n'est pas terminé, le score actuel est affiché: Score actuel: : awayScore - : homeScore. Et enfin, un peu de logique délicate pour identifier quelle période est la partie de hockey ou si elle est dans l'entracte.

Si la variable currentIntermission est fourni dans les résultats, alors j'utilise une fonction que j'ai définie appelée ordinal_suffix_of, qui convertira le numéro de période en lecture: 1ère (2ème, 3ème, etc.).

Quand ce n’est pas en entracte, je cherche le période actuelle valeur. Cela utilise aussi le ordinal_suffix_of  pour montrer que le jeu est en 1ère période (2ème, 3ème, etc.).

En dessous de cela, une autre fonction que j'ai définie appelée temps restant est utilisé pour convertir le nombre de secondes restantes en nombre de minutes et de secondes restantes dans la période. Par exemple: 10:12.

La dernière partie du code affiche le score final car nous savons que le jeu est terminé..

Voici un exemple de ce à quoi il ressemble quand il y a un mélange de jeux finis, de jeux en cours et de jeux qui n'ont pas encore commencé (je ne suis pas un très bon concepteur, donc ça ressemble à ce que l'on attend d'un développeur leur propre interface utilisateur).

La prochaine étape est un morceau de JavaScript qui crée le socket, les fonctions d'assistance ordinal_suffix_of et temps restant, et une variable qui fait référence au modèle jQuery créé.

Le dernier morceau de code est le code permettant de recevoir l'événement socket et de rendre le modèle:

socket.on ('data', fonction (data) console.log (data); $ ('#données'). html (tmpl.render (data.scoreboard.gameScore, helpers)););

J'ai un espace réservé div avec l'id de données. Le résultat du rendu du modèle (tmpl.render) écrit le code HTML dans ce conteneur. Ce qui est vraiment bien, c'est que la bibliothèque JsRender peut accepter un tableau de données, dans ce cas data.scoreboard.gameScore, qui parcourt chaque élément du tableau et crée un jeu par élément.

Voici le HTML final et JavaScript tous ensemble:

   Exemple Socket.IO   

Démarrez l'application Node et accédez à http: // localhost: 3000 pour voir les résultats vous-même.!

Toutes les X minutes, le serveur enverra un événement au client. Le client redessinera les éléments du jeu avec les données mises à jour. Ainsi, lorsque vous laissez le site ouvert et que vous le consultez périodiquement, vous verrez les données s'actualiser lorsque les jeux sont en cours..

Conclusion

Le produit final utilise Socket.io pour créer un serveur auquel les clients se connectent. Le serveur récupère les données et les envoie au client. Lorsque le client reçoit les données, il peut mettre à jour l'affichage de manière transparente. Cela réduit la charge sur le serveur car le client n'effectue de travail que lorsqu'il reçoit un événement du serveur..

Les sockets ne sont pas limités à une direction; le client peut également envoyer des messages au serveur. Lorsque le serveur reçoit le message, il peut effectuer certains traitements..

Les applications de chat fonctionneraient généralement de cette façon. Le serveur recevrait un message du client, puis serait diffusé à tous les clients connectés pour montrer que quelqu'un avait envoyé un nouveau message..

J'espère que vous avez apprécié cet article, car j'ai eu un plaisir fou à créer cette application sportive en temps réel pour l'un de mes sports préférés.!