Il y a quelque temps je vous avais laissé avec une introduction ultra basique de node.js avec l'application qui ne servait à rien si ce n'est à poser quelques bases. Voici la suite.

Dans cet exemple, le but sera de faire un chat basique en Ajax. On va modifier les sources du post précédent pour arriver à nos fins.

Nous avons vu que la base utilisait les templates ejs (pour un cours de rattrapage, c'est par ici, c'est en anglais, mais c'est simple ).

 

Mise en place d’un écran de login basique

Pour un chat, la première chose à faire est s'identifier. On va donc créer un template d'identification tout simple. Celui-ci n'a strictement aucun intérêt, mais c'est plus propre ainsi.

On va donc l'enregistrer dans /views/login.ejs

Il est simplement constitué d'un champ de saisi Username et d'un bouton.

<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
  <form method="post" action="/login">
      <h1>Identification Username</h1>
      <input name="username" autofocus>
      <button>OK</button>
    </form>
  </body>
</html>

 

On va également modifier la route de base pour passer par le login.

Dans /routes/index.js on modifie la route de base de la façon suivante

exports.index = function(req, res){

  res.render('login', { title: 'Login' });

};

 

TEST1

Lancez le test depuis le répertoires “messages”  avec la commande suivante:

supervisor app.js

Allez dans votre navigateur et entrez http://localhost:3000 

Si vous avez l’idée d’entrer un prénom et de valider vous allez obtenir une erreur. Ce qui est normal vu que nous n’avons pas géré la route /login !!!

Vous l’aurez compris cet exemple n’a guère plus d’intérêt que la création de la base node.js.

 

Petite amélioration de App.js et templates index.ejs

 

On va ajouter quelques routes, des variables globales (on sait en php faut jamais, jamais faire ça, ça tombe bien on est pas en php).

Modification du App.js - v2

En haut du app.js on ajoute deux variables globales

var Messages = []; // stockage des messages

var Username = ""; // stokage du Username

 

Ensuite on ajoute 2 routes et un peu de traitements pour ajouter les messages dans le tableau global Messages et la variable Username.

/*
Ajout de la route pour login
*/

app.post('/login',function(req,res) {
  Username = req.body.username;
  res.render('index', {
  title : Username, Username:'',sessionID : req.sessionID, Messages:''
  });
});

/*
 Ajout de la route et le traitement des messages
*/

app.post('/envoyer', function(req,res) {
  if (Username !== "" && Username !== undefined) {
    Messages.push({Username:Username,Texte:req.body.message});
    // on dépaque les messages à l'ancienne
    var val="";
    for (var i=0 in Messages) {
      val += "<li>"+Messages[i].Username + ':' + Messages[i].Texte+"</li>";
    }
    // On envoi les messages vers la page index
    res.render('index',{
      title : 'Messages', Username: Username,sessionID : req.sessionID,Messages : val
    });

  }
  // SI on est pas connecté on envoi vers la page de connexion
  else {
     res.redirect('/');
   }
});

 

Modification du template index.ejs - v2

Ici pas grand chose à faire, juste ajouter un formulaire avec un champ de saisie “message”

<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
    <h1><%= title %></h1>
    <p>Welcome to <%= title %> <%= Username %></p>
    <form id="message" action="envoyer" method="post">
      <label for="message" >Entrez un message></label>
      <input type="text" id="message" name="message"/>
      <button id="buttonsend"> Envoyer </button>
      <ul id="messages">
        <%- Messages %>
      </ul>
    </form>
  </body>
</html> 

 

TEST 2

On lance app.js avec Supervisor si vous l’avez stoppé (ctrl + C)
Sinon Supervisor a du normalement redémarrer app.js. Si pas d’erreur (ce n’est pas lesieur) on doit avoir un truc du style

DEBUG: crashing child
DEBUG: Starting child process with 'node app.js'
Express server listening on port 3000

 

Ce chat ne sert toujours à rien, il faut envoyer un message pour voir les messages des autres !!! et F5 est inhibé.

 

Vous pouvez télécharger l’exemple en cliquant ICI (v2)

NodeJS  img 001

Version avec un peu d’ajax

Pour cette dernière version ultra simple et sans optimisation on va ajouter de l’ajax histoire de ne pas rafraîchir la page mais uniquement les messages.

Modification du template index.ejs - v3

On va transformer un petit peu le template (3 fois rien), un petit bout de javascript. Attention cet exemple ne doit pas fonctionner sous IE (on peut aussi jouer avec Jquery pour simplifier la chose).

On va retirer les balises form et on va ajouter l’ajax

  <script type="text/javascript">
    (function() {
      var httpRequest;
      document.getElementById("buttonsend").onclick = function() { makeRequest('/envoyer'); };

      function makeRequest(url) {
        if (window.XMLHttpRequest) { // Mozilla, Safari, ...
          httpRequest = new XMLHttpRequest();
        } else if (window.ActiveXObject) { // IE
          try {
            httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
          }
          catch (e) {
            try {
              httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
            }
            catch (e) {}
          }
        }

        if (!httpRequest) {
          alert('Giving up :( Cannot create an XMLHTTP instance');
          return false;
        }
        httpRequest.onreadystatechange = modifListMsg;
        httpRequest.open('POST', url);
        httpRequest.setRequestHeader("Content-type","application/x-www-form-urlencoded");
        httpRequest.send("message="+document.getElementById("message").value);
      }

      //on envoi le message
      function modifListMsg() {
        if (httpRequest.readyState === 4) {
          if (httpRequest.status === 200) {
           document.getElementById("messages").innerHTML = httpRequest.responseText;
          } else {
            alert('There was a problem with the request.');
          }
        }

 

Modification du App.js - v3

Dans App.js, on va ajouter une fonction pour récupérer uniquement le tableau de messages. Cette fonction sera appelé en ajax toutes les 3 secondes

 

On va modifier la fonction de d’ajout dans le tableau en ajoutant un contrôle pour éviter les messages vides.

On va également ajouter une route pour récupérer uniquement le tableau de messages.

app.post('/envoyer', function(req,res) {
  if (Username !== "" && Username !== undefined) {
    if (req.body.message !== undefined && req.body.message !== '') {
      Messages.push({Username:Username,Texte:req.body.message});
    } else {
      sendMessages(res);
    }
  }
  // SI on est pas connecté on envoi vers la page de connexion
  else {
     res.redirect('/');
  }
});

//appel pour l'affichage des messages
app.post('/messages', function (req,res) {
  sendMessages(res);
}); 


//----

// envoi des messages en réponse à un appel
function sendMessages(res) {
  var val="";
  for (var i=0 in Messages) {
    val += "<li>"+Messages[i].Username + ':' + Messages[i].Texte+"</li>";
  }
  // On envoi les messages vers la page index
  res.send(val);
} 

 

 

TEST3

Le système semble parfaitement fonctionner. Il existe un bug qui fait que de temps à autre le dernier message envoyé, est à nouveau envoyé … Je n’ai pas recherché la cause de ce phénomène étrange.

Vous pouvez télécharger le code tout moisi ici (v3)

NodeJS  img 002 NodeJS  img 003

Conclusion

Nous avons un chat basique fonctionnel qui ne nous a couté quasi aucun effort (on aurait pu faire exactement la même chose tout aussi facilement en PHP). Il n’est absolument pas optimisé. Toutes les 3 secondes, un navigateur est susceptible d’appeler le serveur et chose encore plus drôle lorsque les sessions expirent les messages s’effacent (normal).
Autres soucis les messages sont stockés dans un tableau, si le serveur tombe, tous les messages sont perdus. De plus cela risque d’utiliser beaucoup de mémoire à la longue. On ne connait pas non plus la date et l’heure du post du message. SI on fait F5 on renvoie le dernier message. Bref ce n’est pas top, il s’agit d’un cas d’étude.

D’autre part le code pourrait connaitre de nombreuses optimisations. La mise en module par exemple pourrait en être une. L’optimisation de l’écriture du code lui-même avec l’utilisation objet des fonctions, etc…

L’avantage de l’avoir réalisé avec NodeJS est sa grande réactivité et vitesse.

Dans un prochain POST, on va ajouter une base de données pour ne plus perdre les messages. On va utiliser les sockets plutôt un petit Ajax, on va horodaté les messages.

Comments powered by CComment

We use cookies

Nous utilisons des cookies sur notre site web. Certains d’entre eux sont essentiels au fonctionnement du site et d’autres nous aident à améliorer ce site et l’expérience utilisateur (cookies traceurs). Vous pouvez décider vous-même si vous autorisez ou non ces cookies. Merci de noter que, si vous les rejetez, vous risquez de ne pas pouvoir utiliser l’ensemble des fonctionnalités du site.