##### Socket.io ##### Maintenant que nous avons une base avec un ``Hello World``, nous allons rajouter une fonctionnalité pour que vous puissiez mieux comprendre le fonctionnement de ``socket.io`` dans cette application. .. warning:: Dans cette section, nous verrons juste comment intégrer ``socket.io`` à notre ``Hello World`` pour que l'application reste bien structurée (le fonctionnement général de ``socket.io`` étant expliqué sous ``pré-requis``). Code côté serveur ----- Tout d'abord, nous allons créer un nouveau fichier nommé ``socket.js`` que nous mettrons dans le dossier ``serveur``. .. only:: html .. code-block:: tree :emphasize-lines: 4 . └── serveur ├── routes.js └── socket.js .. only:: latex .. code-block:: sh :emphasize-lines: 4 . `-- serveur |-- routes.js `-- socket.js Dans ce fichier, nous écrivons le code suivant : .. captionup:: ./serveur/socket.js .. code-block:: javascript // comme dans le fichier routes.js, la fonction principale est lancée depuis app.js // nous passons le paramètre io, qui contient le module socket.io, depuis app.js exports.f = function(io) { /* cette fonction de callback s'exécute à chaque fois qu'un client émet l'événement "connection" */ io.on('connection', function (socket) { /* lorsque le client effectue un socket.emit('bouton_client'), cette fonction s'exécute */ socket.on('bouton_client', function(){ console.log('Le client a cliqué sur le bouton !') }); }); } Nous exécutons un ``require`` pour que ``app.js`` charge le module ``socket.io`` : .. captionup:: ./app.js .. code-block:: javascript var io = require('socket.io')(server); Nous chargeons le fichier ``socket.js`` : .. captionup:: ./app.js .. code-block:: javascript var socket = require('./serveur/socket.js'); Puis, nous demandons à ``app.js`` d'exécuter la fonction que nous venons de créer en lui passant le module ``socket.io`` : .. captionup:: ./app.js .. code-block:: javascript socket.f(io); Votre fichier ``app.js`` devrait alors ressembler à ceci : .. captionup:: ./app.js .. code-block:: javascript var http = require('http'); var path = require('path'); var express = require('express'); // nous faisons appel à expressJS en tapant app.nom_de_la_fonction() var app = express(); var server = http.Server(app); var io = require('socket.io')(server); var routes = require('./serveur/routes.js'); var socket = require('./serveur/socket.js'); // appel de la fonction qui se trouve dans "routes.js" routes.f(app, __dirname); // appel de la fonction qui se trouve dans "socket.js" socket.f(io); server.listen(8888); .. important:: Il est essentiel de respecter l'ordre des ``require``. Comme vous pouvez le constater, certains modules dépendent d'autres modules. C'est par exemple le cas de ``socket.io`` qui a besoin de la variable ``server``, qui nécessite elle-même la variable ``app`` d'``expressJS`` pour fonctionner correctement. Si vous inversez l'ordre de ces instructions, des erreurs peuvent survenir. Code côté client ----- Maintenant que le serveur peut faire fonctionner ``socket.io``, il reste quelques modifications à effectuer du côté client. Nous commençons par ajouter une ligne au début du fichier ``general.js`` : .. captionup:: ./static/js/general.js .. code-block:: javascript var socket = io.connect('http://' + window.location.host); .. tip:: ``window.location.host`` contient le nom de domaine avec le port sur lequel est connecté le client. En l'occurence, cette commande équivaut à ceci : .. code-block:: javascript var socket = io.connect('http://localhost:8888') Ensuite, nous ouvrons un nouveau fichier pour séparer le ``javascript`` du ``HTML`` sur le côté client. .. only:: html .. seealso:: Mais pourquoi ne pas utiliser ``general.js`` ? .. only:: latex .. hint:: Mais pourquoi ne pas utiliser ``general.js`` ? Parce que ce fichier contient des fonctions ``javascript`` qui s'appliquent à toutes les pages de l'application. Dans notre cas, le ``socket.emit`` ne sert qu'à une seule page, ``index.ejs``. Il faudra donc plutôt créer un fichier du nom de ``index.js`` : .. only:: html .. code-block:: tree :emphasize-lines: 5 . └── static └── js ├── general.js └── index.js .. only:: latex .. code-block:: sh :emphasize-lines: 5 . `-- static `-- js |-- general.js `-- index.js Dans ce fichier, nous rédigeons une fonction avertit le serveur que le client a interagi avec la page web : .. captionup:: ./static/js/index.js .. code-block:: javascript function avertir_serveur() { socket.emit('bouton_client'); } Ensuite, nous ajoutons un bouton qui exécutera cette fonction lorsqu'il sera cliqué sur la page ``index.ejs`` : .. captionup:: ./views/index.ejs .. code-block:: html N'oublions pas de faire référence au fichier ``index.js`` que nous venons de réaliser en ajoutant cette ligne juste avant la fin de la balise ``head`` : .. captionup:: ./views/index.ejs .. code-block:: html Notre page ``index.ejs`` contient alors contenir ceci : .. captionup:: ./views/index.ejs .. code-block:: guess <% include balise_head %> <% include barre_navigation %>

Hello World !

.. tip:: Vous remarquerez que nous faisons référence au fichier ``index.js`` juste après l'inclusion de la balise ``head``. Alors pourquoi ne pas mettre cette ligne dans le fichier ``balise_head`` ? Tout simplement parce que la page ``index.ejs`` est la seule à avoir besoin de ce fichier. Il est donc inutile de demander aux autres pages de le charger alors qu'elles n'utilisent pas les fonctions que contient ce fichier. Enfin, nous incluons le fichier ``socket.io.js`` dans ``balise_head.ejs`` pour que le client reconnaisse la fonction ``socket.emit()`` : .. captionup:: ./views/balise_head.ejs .. code-block:: html .. warning:: Cette balise doit apparaître avant l'appel de ``general.js``. Sinon, le navigateur ne trouvera pas la variable ``io`` lors de l'exécution de l'instruction qui permet d'initier la connexion ``socket.io`` entre le client et le serveur. Résultat ----- Et voilà ! Maintentant, si nous relançons notre serveur, nous obtenons la page suivante : .. image:: structure_base/7.png :height: 10000 px :width: 700 px :scale: 60 % En cliquant sur le bouton, un message s'affiche dans la console du serveur : .. code-block:: bash Le client a cliqué sur le bouton ! Le client a cliqué sur le bouton ! ... .. only:: html .. tip:: Vous pouvez télécharger le contenu du programme actuel en cliquant `ici`_. .. only:: latex .. tip:: Vous pouvez télécharger le conteu du programme actuel à l'aide ce ce lien : http://j.mp/1RkJmCq .. liens .. _ici: http://tutoriel-forum.s3-website-eu-west-1.amazonaws.com/hw_socket-io.zip