Fermer

septembre 4, 2019

Construire une application de vote en temps réel avec poussoir, nœud et bootstrap –


Dans cet article, je vais vous expliquer comment construire une application Web de vote à domicile Harry Potter en temps réel.

Les applications en temps réel utilisent généralement WebSockets, un type de protocole de transfert relativement nouveau, par opposition à HTTP, qui est une communication à sens unique ne se produisant que lorsque l'utilisateur le demande. Les WebSockets permettent une communication persistante entre le serveur et l'utilisateur, ainsi que tous les utilisateurs connectés à l'application, tant que la connexion est maintenue ouverte.

Une application Web en temps réel est une application où l'information est transmise (presque) instantanément entre utilisateurs et le serveur (et, par extension, entre les utilisateurs et les autres utilisateurs). Cela contraste avec les applications Web traditionnelles où le client doit demander des informations au serveur. – Quora

 applications connectées

Notre application Web de vote Harry Potter affiche les options (les quatre maisons) et un graphique à droite qui se met à jour lorsque l'utilisateur connecté vote.

une brève idée de l'apparence et de la convivialité, l'application finale va ressembler à ceci:

 Harry Potter avec le graphique JS

Voici un petit aperçu du fonctionnement de l'application en temps réel: [19659006]

Pour rendre notre application en temps réel, nous allons utiliser Pusher et WebSockets. Pusher constitue une couche en temps réel entre vos serveurs et vos clients. Il maintient des connexions persistantes avec les clients – via un WebSocket si possible, et revient à la connectivité basée sur HTTP – de sorte que, dès que vos serveurs disposent de nouvelles données à transmettre aux clients, ils peuvent le faire instantanément via Pusher. [19659010] Construction de notre application

Créons notre nouvelle application à l'aide de la commande npm init . On vous posera de manière interactive quelques questions sur les détails de votre candidature. Voici ce que j’avais:

 praveen@praveen.science ➜ Harry-Potter-Pusher $ npm init
{
  "nom": "harry-potter-pusher",
  "version": "1.0.0",
  "description": "Une application de vote en temps réel utilisant la sélection de maison de Harry Potter pour mon article sur Pusher.",
  "main": "index.js",
  "scripts": {
    "test": "echo " Erreur: aucun test spécifié  "&& exit 1"
  },
  "référentiel": {
    "type": "git",
    "url": "git + https: //github.com/praveenscience/Harry-Potter-Pusher.git"
  },
  "keywords": [
    "Harry_Potter",
    "Pusher",
    "Voting",
    "Real_Time",
    "Web_Application"
  ],
  "auteur": "Praveen Kumar Purushothaman",
  "licence": "ISC",
  "bogues": {
    "url": "https://github.com/praveenscience/Harry-Potter-Pusher/issues"
  },
  "homepage": "https://github.com/praveenscience/Harry-Potter-Pusher#readme"
}

Est-ce correct? (Oui)

J'ai donc laissé la plupart des paramètres avec des valeurs par défaut. Il est maintenant temps d’installer les dépendances.

Installation des dépendances

Nous avons besoin d’express, de l’analyseur de corps, du partage de ressources à origine croisée (CORS), de Mongoose et de Pusher installés en tant que dépendances. Pour tout installer en une seule commande, utilisez ce qui suit. Vous pouvez également consulter le résultat de cette commande.

 praveen@praveen.science P Harry-Potter-Pusher $ npm j'exprime un analyseur de corps cors pusher mangeant
npm notice a créé un fichier de verrouillage sous le nom package-lock.json. Vous devriez commettre ce fichier.
npm WARN ajv-keywords@3.2.0 requiert un homologue de ajv@^6.0.0 mais aucun n'est installé. Vous devez installer vous-même les dépendances entre homologues.

+ pousseur@2.1.2
+ body-parser@1.18.3
+ mangouste@5.2.6
+ cors@2.8.4
+ express@4.16.3
ajouté 264 paquets en 40.000

Exiger nos modules

Comme il s'agit d'une application Express, nous devons inclure express () [) en tant que première chose. Ce faisant, nous avons également besoin de quelques modules d’accompagnement. Commençons par ceci:

 const express = require ("express");
const path = require ("path");
const bodyParser = require ("analyseur de corps");
const cors = require ("cors");

Création de l’application Express

Commençons par la création de notre application Express maintenant. Pour commencer, nous devons obtenir l'objet renvoyé de la fonction express () affectée à une nouvelle variable app :

 const app = express ();

Gestion des actifs statiques

L'ajout de la ligne ci-dessus après le jeu d'inclusions initial initialisera notre application en tant qu'application Express. La prochaine chose que nous devons faire est de configurer les ressources statiques. Créons un nouveau répertoire dans notre projet actuel appelé public et utilisons le middleware statique d’Express pour servir les fichiers statiques. Dans le répertoire, créons un simple fichier index.html qui indique «Hello, World»:



  
    
    
     Hello, World 
  
  
     Hello, World!
  

Pour servir les fichiers statiques, nous avons une fonction intégrée .use () avec express.static () dans Express. La syntaxe est la suivante:

 app.use (express.static (path.join (__ nomr, "public")));

Nous devons également utiliser le middleware d'analyse syntaxique de corps pour que le contenu HTTP POST en tant que JSON soit accessible au sein du req.body . Nous allons également utiliser le code pour obtenir le middleware qui analyse uniquement les corps et le coder et examiner uniquement les requêtes dans lesquelles l'en-tête Content-Type correspond au type option. Cet analyseur accepte uniquement le codage UTF-8 du corps et prend en charge l’inflation automatique des codages gzip et déflate :

 app.use (bodyParser.json ());
app.use (bodyParser.urlencoded ({extended: false}));

Pour autoriser les demandes interdomaines, nous devons activer CORS. Actionnons le module CORS en utilisant le code suivant:

 app.use (cors ());

Maintenant, toute la configuration initiale a été définie. Il ne nous reste plus qu'à configurer un port et à écouter les connexions entrantes sur le port spécifique:

 const port = 3000;
app.listen (port, () => {
  console.log (`Le serveur a démarré sur le port $ {port} .`);
});

Assurez-vous que votre app.js final ressemble à ceci:

 const express = require ("express");
const path = require ("path");
const bodyParser = require ("analyseur de corps");
const cors = require ("cors");

// Créer une application.
const app = express ();

// Servir les fichiers statiques du public.
app.use (express.static (path.join (__ dirname, "public")));

// Inclut le middleware analyseur de corps.
app.use (bodyParser.json ());
app.use (bodyParser.urlencoded ({extended: false}));

// Activer CORS.
app.use (cors ());

// Définit le port.
port constant = 3000;
// écoute les connexions entrantes.
app.listen (port, () => {
  console.log (`Le serveur a démarré sur le port $ {port} .`);
});

Exécutez la commande pour démarrer le serveur:

 $ npm run dev

Ouvrez votre http: // localhost: 3000 / sur un nouvel onglet et voyez la magie. Vous devriez voir une nouvelle page avec «Hello, World».

 Aperçu de Hello World dans le navigateur

Création de la fin de l'application (19659011) Commençons par créer un répertoire appelé routes et créez un fichier dedans, disons vote.js . Nous devons connecter ce fichier à notre fichier app.js . Revenons-y et intégrons-le sous notre initialisation express () :
 const app = express (). ;

// Votez route.
const vote = require ("./ routes / vote")

Le répertoire routes se trouvant dans le même répertoire que le app.js nous commencerons par ./ . Pour pouvoir utiliser celui-ci avec le routeur, passons au bas de la page et ajoutons le code de logiciel intermédiaire de routeur indiqué ci-dessous avant la définition du port:

 app.use ("/ vote", vote);

Tout ce qui passe par l'URL / vote sera traité par le fichier vote.js fourni par la variable .

Traitement des demandes GET et POST

A l'aide de l'instance de routeur d'Express, nous pouvons gérer les méthodes GET et POST via notre chemin / vote . Créons un itinéraire par défaut GET et envoyons un texte par défaut avec le nom: "Vous êtes dans /vote".

const express = require (" express ");
const router = express.Router ();

// Par défaut get route.
router.get ("/", (req, res) => {
  res.send ("Vous êtes dans / vote");
});

Le code ci-dessus achemine toutes les demandes du chemin / vote vers nos routes / vote.js nouvellement formées.

Traitement des demandes POST

Nous avons également besoin d'un Gestionnaire POST où nous pouvons déclencher l'API Pusher. Router.post () pour les demandes POST adressées à / afin que toutes les demandes soient envoyées à / vote . à cause de notre middleware. Nous allons donner le même type de fonctions fléchées ici, et envoyons un message comme celui-ci: "Vous avez posté à /vote.":

// Route POST par défaut.
router.post ("/", (req, res) => {
  res.send ("Vous avez POSTÉ / voté.");
});

La fonction res.send () sera remplacée par les appels d'API Pusher à l'avenir.

Exportation du routeur

Enfin, nous devons exporter le routeur en tant que module. Utilisez le module.exports comme ceci à la fin. Cela devrait être la fin du fichier, bien que vous puissiez l'avoir n'importe où. N'oubliez pas que JavaScript est orienté événement et non pas procédural:

 // Exportez le routeur.
module.exports = routeur;

À ce stade, lorsque vous voyez le fichier complet vote.js il devrait ressembler à ceci:

 const express = require ("express");
const router = express.Router ();

// Route GET par défaut.
router.get ("/", (req, res) => {
  res.send ("Vous êtes dans / vote.");
});

// Route POST par défaut.
router.post ("/", (req, res) => {
  res.send ("Vous avez POSTÉ / voté.");
});

// Exporte le routeur.
module.exports = routeur;

Assurez-vous de tout sauvegarder et essayez à présent d'exécuter les deux URL dans notre navigateur Web.

Vous devriez voir une sortie dans vos navigateurs Web.

Intégration à l'API Pusher

Commençons par modifier le code. nous avons écrit pour le gestionnaire POST – celui que nous avons écrit dans le fichier vote.js . Voici ce que nous voulons réellement déclencher Pusher. Passons rapidement à notre tableau de bord Pusher et sélectionnez votre application Pusher ( de praveen-science-app dans mon cas) et cliquez sur l’onglet Getting Started . Vous verrez le code à lancer.

Dans notre vote.js nous devons définir (ou exiger) la bibliothèque Pusher. Ensuite, nous devons créer une nouvelle instance (un objet) de la classe Pusher puis déclencher le service de pousseurs à l'intérieur de la POST . Je modifie le fichier vote.js comme indiqué ci-dessous:

Remarque: veillez à modifier votre appId clé . ] secret à celui indiqué dans le tableau de bord.

 const express = require ("express");
const router = express.Router ();

// ///// Étape 1: Inclure le pousseur ///// //
const Pusher = require ('poussoir');

// ///// Etape 2: Instancier un objet ///// //
const pusher = new Pusher ({
  appId: 'appId',
  clé: 'clé',
  secret: 'secret',
  cluster: 'eu',
  crypté: vrai
});

// Route GET par défaut.
router.get ("/", (req, res) => {
  res.send ("Vous êtes dans / vote.");
});

// Route POST par défaut.
router.post ("/", (req, res) => {
  // ///// Étape 3: déclencher le service Pusher ///// //
  pusher.trigger ('my-channel', 'my-event', {
    "message": "bonjour le monde"
  });
});

// Exporte le routeur.
module.exports = routeur;

Dès qu'un utilisateur soumet le formulaire, notre application envoie une demande POST à cette route, qui va frapper l'API Pusher et déclencher le service Pusher à l'aide de pusher.trigger (). appel de fonction. De plus, nous ne voulons pas utiliser les valeurs par défaut de my-channel et my-event changeons-les donc en hp-vote et . ] hp-house . Nous n'avons pas non plus besoin d'envoyer un message mais plutôt de donner des points et la maison :

 router.post ("/", (req, res) => {
  pusher.trigger ('vote-hp', 'maison-hp', {
    "points": 1,
    "maison": req.body.house
  });

});

Pour l'instant, nous allons attribuer une valeur de 1 aux points (je vais expliquer pourquoi prochainement), et nous utilisons req. body.house pour la maison car la valeur doit provenir des données de formulaire fournies à l'aide de req.body comme nous utilisez l'analyseur de corps .

Enfin, nous allons renvoyer un JSON au navigateur en réponse à l'aide de la fonction res.json () et transmettre un objet avec un booléen success et un message remerciant l'utilisateur pour son vote et sa réception:

 router.post ("/", (req, res) => {
  pusher.trigger ('vote-hp', 'maison-hp', {
    "points": 1,
    "maison": req.body.house
  });

  retourne res.json ({
    "succès": vrai,
    "message": "Merci d'avoir voté."
  });
});

Création de l’application frontale de l’application

J’ai utilisé jQuery et Bootstrap pour l’application frontale. Voici la partie où nous permettons aux utilisateurs de voter.

 Formulaire de Harry Potter

Je vais également ajouter un conteneur de graphique qui affichera les graphiques en temps réel à mesure que les votes sont reçus. ]  App Harry Potter Page de destination après l'ajout de Logo

Tout intégrer

Nous avons déjà terminé le back-office. Nous allons maintenant voir comment envoyer la demande au service Poussoir lorsque le bouton de vote est cliqué, grâce au JavaScript frontal. Nous allons déclencher l'événement submit du formulaire lorsque l'utilisateur clique sur le bouton. Il doit alors envoyer une demande POST à notre extrémité du chemin / vote .

Listener d’événements, données utilisateur et Ajax

Ajoutons un écouteur d’événements pour notre soumission de formulaire, un code pour la capture des données utilisateur et l’appel Ajax:

 // Exécuter seulement après que le document entier soit récupéré et les actifs sont chargés.
$ (document) .ready (fonction () {
  // écouteur d'événement de soumission de formulaire (gestionnaire d'événement)
  $ ("# voteForm"). submit (fonction (e) {
      e.preventDefault ();
      // Récupère la valeur de l'élément d'entrée coché.
      var house = $ (". form-check-input: vérifié"). val ();
      // Construit les données à envoyer comme charge utile à l'appel AJAX.
      var data = {
          "maison Maison
      };
      $ .post ("/ vote", données, fonction (res) {
          // Journalise la sortie dans la console.
          console.log (res);
        });
    });
});

Utilisation du pousseur et des graphiques

Lorsque le formulaire est soumis, l'appel Ajax déclenche le point de terminaison / vote et l'application de nœud dorsal déclenchera également le service Pusher à l'aide du code ci-dessous dans routes / vote.js :

 pusher.trigger ('vote hp', 'hp-house', {
  "points": 1,
  "maison": req.body.house
});

Lorsque le code ci-dessus est frappé (ou exécuté), le service Pusher déclenchera un événement avec hp-vote et hp-house . Nous ne prenons pas l'événement ni ne l'abonnons encore. Nous allons donc implémenter CanvasJS pour construire notre graphique, nous allons souscrire à l'événement ci-dessus et ajouter les points de données par le déclencheur, spécifié par l'écouteur d'événement submit du formulaire. [19659086] Ajout de CanvasJS

Une fois tous les bits ajoutés correctement, votre script.js côté client doit ressembler à ceci:

 // N'exécutez que lorsque le document entier est récupéré et les actifs sont chargé.
$ (document) .ready (fonction () {
  // écouteur d'événement de soumission de formulaire (gestionnaire d'événement)
  $ ("# voteForm"). submit (fonction (e) {
    // Empêche l'événement par défaut.
    e.preventDefault ();
    // Récupère la valeur de l'élément d'entrée coché.
    var house = $ (". form-check-input: vérifié"). val ();
    // Construit les données à envoyer comme charge utile à l'appel Ajax.
    var data = {
      "maison Maison
    };
    // Lance l'appel Ajax de requête POST vers notre point final / vote.
    $ .post ("/ vote", données, fonction (res) {
      // Journalise la sortie dans la console.
      console.log (res);
    });
  });
  // Crée les points de données de base.
  var dataPoints = [
    {
      label: "Gryffindor",
      y: 0
    }, {
      label: "Hufflepuff",
      y: 0
    }, {
      label: "Ravenclaw",
      y: 0
    }, {
      label: "Slytherin",
      y: 0
    }
  ];
  // Initialise le graphique à l'aide du sélecteur jQuery.
  // Récupère l'élément conteneur graphique.
  var chartContainer = $ ("# chartContainer");
  // Vérifie si l'élément existe dans le DOM.
  if (chartContainer.length === 1) {
    // Construit les options pour le graphique.
    var options = {
      "animationEnabled": true,
      "theme": "light1",
      "Titre": {
        "text": "Résultats de la Maison Harry Potter"
      },
      "data": [
        {
          "type": "column",
          "dataPoints": dataPoints
        }
      ]
    };
    // Initialise le graphique.
    $ ("# chartContainer"). CanvasJSChart (options);
  }
});

Enregistrez maintenant le fichier et, lorsque vous rechargerez la page, vous devriez pouvoir voir un graphique de substitution. C'est vraiment un vrai graphique mais sans aucune valeur. Vous devriez pouvoir voir quelque chose comme ceci:

 Harry Potter avec le graphique JS

Nous avons maintenant implémenté notre graphique CanvasJS du côté droit.

Initialisation du pousseur du côté client [19659093] Après l'enregistrement par pousseur, nous devons initialiser l'objet Pusher . Comme nous avons déjà un config.js côté client, nous utiliserons ce code dans cette partie:
 // Initialise un objet pousseur.
var pusher = new Pusher (PusherConfig.key, {
  cluster: PusherConfig.cluster,
  forceTLS: PusherConfigforceTLS.
});

Après l'initialisation de l'objet Pusher, nous devons nous abonner à notre canal, où nos messages sont publiés par le serveur. Nous allons copier le code du tableau de bord Pusher, mais nous allons changer un peu pour nous abonner à notre événement hp-vote et hp-house . Les valeurs par défaut de my-channel et my-event doivent être mises à jour de la même manière en relation avec notre code back-end:

 // Subscribe to the channel.
var channel = pusher.subscribe ('vote hp');
// Lier à un événement particulier et écouter les données de l'événement.
channel.bind ('hp-house', fonction (données) {
  alerte (JSON.stringify (données));
});

Au lieu de alert d'un message de données nous souhaitons essentiellement ajouter les données au graphique. Nous pouvons y arriver en prenant nos dataPoints et en manipulant le tableau par rapport à la réponse du serveur. Avec la variable déjà existante de dataPoints (rappelez-vous que nous avons utilisé var au lieu de const car nous devrions pouvoir le changer à un stade ultérieur), Je vais utiliser une fonction de rang supérieur Array.map () comme suit:

 // Lier à un événement particulier et écouter les données de l'événement.
channel.bind ('hp-house', fonction (données) {
  // Utiliser une carte de tableau d'ordre supérieur.
  dataPoints = dataPoints.map (fonction (d) {
    // Vérifie si l'étiquette actuelle est la valeur mise à jour.
    if (d.label == data.house) {
      // Incrémente la valeur de la maison du nombre de nouveaux points.
      d.y + = data.points;
    }
    // Retourne la valeur d'origine car il s'agit d'une fonction de la carte.
    retour d;
  });
});

Nous parcourons toutes les étiquettes dataPoints et, lorsqu'une étiquette particulière correspond à l'étiquette actuelle, nous incrémentons la valeur de l'étiquette actuelle avec le nombre de points mis à jour. Comme nous utilisons une fonction JavaScript Array.map () nous devons renvoyer la valeur initiale, d à l’appel de la fonction. Une fois que nous avons mis à jour les dataPoints nous devons retransformer le graphique.

Après la fonction de la carte () nous allons procéder comme suit:

 channel .bind ('hp-house', fonction (données) {
  // Utiliser une carte de tableau d'ordre supérieur.
  dataPoints = dataPoints.map (fonction (d) {
    // Vérifie si l'étiquette actuelle est la valeur mise à jour.
    if (d.label == data.house) {
      // Incrémente la valeur de la maison du nombre de nouveaux points.
      d.y + = data.points;
    }
    // Retourne la valeur d'origine car il s'agit d'une fonction de la carte.
    retour d;
  });

  // Re-rend le graphique.
  $ ("# chartContainer"). CanvasJSChart (options);
});

Une fois que vous avez écrit tout le code ci-dessus, enregistrez et exécutez l'application dans votre navigateur, lancez vos outils de développement Web et consultez la console. Vous devriez voir que le service Pusher communique avec votre application. J'ai pu voir ce qui suit dans ma console (j'ai caché mes applications (19459015) et secrètes si bien que toutes les informations sensibles sont affichées:

 Pusher in Console

Conclusion

À ce stade, lorsque vous essayez d'ouvrir deux fenêtres de la même application et que vous votez sur un seul écran, vous pouvez voir tous les écrans se mettre à jour en même temps. Voici comment vous utilisez le service Poussoir pour créer des applications en temps réel.

Notre application Web de vote Harry Potter affiche désormais des options (les quatre maisons) et un graphique à droite qui se met à jour lorsqu'un utilisateur connecté vote. La prochaine étape évidente consisterait à utiliser une base de données, telle que MongoDB, pour stocker toutes les informations afin de garantir leur persistance, même lorsque nous rechargerons les pages de l'application.




Source link