Ni HTML ni HTTP n'ont été créés pour les applications Web dynamiques. Nous nous basons essentiellement sur des hacks, au-dessus de ceux-ci, pour donner à nos applications une interface utilisateur réactive. AngularJS supprime certaines limitations du langage HTML, ce qui nous permet de créer et de gérer plus facilement le code de l'interface utilisateur. Socket.IO, en revanche, nous aide à envoyer des données du serveur non seulement lorsque le client le demande, mais également lorsque le serveur en a besoin. Dans cet article, je vais vous montrer comment combiner ces deux éléments pour améliorer la réactivité de vos applications à page unique..
Dans la première partie de ce didacticiel, nous allons créer un service AngularJS réutilisable pour Socket.IO. À cause de ça réutilisable partie, ce sera un peu plus délicat que de simplement utiliser module.service ()
ou module.factory ()
. Ces deux fonctions ne sont que du sucre syntaxique en plus des fonctions de bas niveau. module.provider ()
méthode, que nous utiliserons pour fournir certaines options de configuration. Si vous n'avez jamais utilisé AngularJS auparavant, je vous conseille vivement de suivre au moins le tutoriel officiel et certains des tutoriels ici sur Tuts+.
Avant de commencer à écrire notre module AngularJS, nous avons besoin d’un back-end simple pour les tests. Si vous connaissez déjà Socket.IO, vous pouvez simplement faire défiler l'écran jusqu'à la fin de cette section, copier le fichier source et passer au point suivant, si ce n'est pas le cas - lisez la suite.
Nous n'aurons besoin que socket.io
. Vous pouvez l’installer directement à l’aide de la touche npm
commande comme ceci:
npm installer socket.io
Ou créer un package.json
fichier, mettez cette ligne dans le les dépendances
section:
"socket.io": "0.9.x"
Et exécuter le npm installer
commander.
Comme nous n’avons besoin d’aucune infrastructure Web complexe comme Express, nous pouvons créer le serveur à l’aide de Socket.IO:
var io = require ('socket.io') (8080);
C'est tout ce dont vous avez besoin pour configurer le serveur Socket.IO. Si vous démarrez votre application, vous devriez voir une sortie similaire dans la console:
Et vous devriez pouvoir accéder au socket.io.js
fichier dans votre navigateur à http: // localhost: 8080 / socket.io / socket.io.js:
Nous allons gérer toutes les connexions entrantes dans le lien
auditeur d'événement du io.sockets
objet:
io.sockets.on ('connexion', fonction (socket) );
le prise
L'attribut transmis au rappel est le client qui s'est connecté et nous pouvons écouter les événements qui s'y trouvent..
Nous allons maintenant ajouter un écouteur d'événements de base dans le rappel ci-dessus. Il enverra les données reçues au client en utilisant le socket.emit ()
méthode:
socket.on ('echo', fonction (données) socket.emit ('echo', données););
écho
est le nom de l'événement personnalisé que nous utiliserons plus tard.
Nous utiliserons également les remerciements dans notre bibliothèque. Cette fonctionnalité vous permet de passer une fonction en tant que troisième paramètre de socket.emit ()
méthode. Cette fonction peut être appelée sur le serveur pour renvoyer certaines données au client:
socket.on ('echo-ack', fonction (données, rappel) rappel (données););
Cela vous permet de répondre au client sans qu'il soit obligé d'écouter les événements (ce qui est utile si vous souhaitez simplement demander des données au serveur)..
Notre test est maintenant terminé. Le code devrait ressembler à ceci (c'est le code que vous devriez copier si vous avez omis cette section):
var io = require ('socket.io') (8080); io.sockets.on ('connexion', fonction (socket) socket.on ('echo', fonction (données) socket.emit ('echo', données);); socket.on ('echo-ack ', fonction (données, rappel) rappel (données);););
Vous devriez maintenant lancer l'application et la laisser en marche avant de continuer avec le reste du tutoriel..
Nous aurons bien sûr besoin de HTML pour tester notre bibliothèque. Nous devons inclure AngularJS, socket.io.js
de notre back-end, notre angular-socket.js
bibliothèque et un contrôleur AngularJS de base pour exécuter certains tests. Le contrôleur sera en ligne dans le du document pour simplifier le flux de travail:
C'est tout ce dont nous avons besoin pour l'instant, nous reviendrons plus tard sur la balise de script vide car nous n'avons pas encore la bibliothèque..
Dans cette section, nous allons créer le angular-socket.js
bibliothèque. Tout le code doit être inséré dans ce fichier.
Commençons par créer le module pour notre bibliothèque:
var module = angular.module ('socket.io', []);
Nous n'avons pas de dépendances, donc le tableau dans le deuxième argument de angular.module ()
est vide, mais ne l'enlevez pas complètement ou vous obtiendrez un $ injecteur: nomod
Erreur. Cela se produit parce que la forme à un argument de angular.module ()
récupère une référence au module déjà existant, au lieu d'en créer un nouveau.
Les fournisseurs sont l’un des moyens de créer des services AngularJS. La syntaxe est simple: le premier argument est le nom du service (pas le nom du fournisseur!) Et le second est la fonction constructeur du fournisseur:
module.provider ('$ socket', $ socketProvider () );
Pour rendre la bibliothèque réutilisable, nous devrons autoriser des modifications dans la configuration de Socket.IO. Définissons d’abord deux variables qui contiendront l’URL de la connexion et l’objet de configuration (le code de cette étape va au $ socketProvider ()
une fonction):
var ioUrl = "; var ioConfig = ;
Maintenant, puisque ces variables ne sont pas disponibles en dehors de la $ socketProvider ()
fonction (ils sont genre de privé), nous devons créer des méthodes (setters) pour les changer. Nous pourrions bien sûr les faire Publique comme ça:
this.ioUrl = "; this.ioConfig = ;
Mais:
Function.bind ()
plus tard pour accéder au contexte approprié pour ce
faux
comme le 'délai de connexion'
optionUne liste complète des options pour le client de Socket.IO peut être consultée sur leur wiki GitHub. Nous allons créer un setter pour chacun d'eux et un pour l'URL. Toutes les méthodes se ressemblent, je vais donc expliquer le code de l'une d'elles et mettre le reste ci-dessous.
Définissons la première méthode:
this.setConnectionUrl = fonction setConnectionUrl (url)
Il convient de vérifier le type de paramètre passé dans:
if (typeof url == 'string')
Si c'est celui auquel nous nous attendions, définissez l'option:
ioUrl = url;
Si non, il faut jeter Erreur-type
:
else jeter un nouveau TypeError ('url doit être du type chaîne'); ;
Pour le reste d'entre eux, nous pouvons créer une fonction d'assistance pour la garder au sec:
function setOption (nom, valeur, type) if (typeof valeur! = type) renvoie un nouveau TypeError ("'" "+ nom +" "doit être de type" "+ type +" ""); ioConfig [nom] = valeur;
Il jette juste Erreur-type
si le type est incorrect, sinon définit la valeur. Voici le code pour le reste des options:
this.setResource = fonction setResource (valeur) setOption ('ressource', valeur, 'chaîne'); ; this.setConnectTimeout = fonction setConnectTimeout (valeur) setOption ('délai de connexion', valeur, 'nombre'); ; this.setTryMultipleoutes = fonction setTryMultipleoutes (valeur) setOption ('try multiple transports', valeur, 'boolean'); ; this.setReconnect = fonction setReconnect (valeur) setOption ('reconnect', valeur, 'boolean'); ; this.setReconnectionDelay = fonction setReconnectionDelay (valeur) setOption ('délai de reconnexion', valeur, 'nombre'); ; this.setReconnectionLimit = fonction setReconnectionLimit (valeur) setOption ('limite de reconnexion', valeur, 'nombre'); ; this.setMaxReconnectionAttempts = fonction setMaxReconnectionAttempts (valeur) setOption ('tentatives de reconnexion maximales', valeur, 'nombre'); ; this.setSyncDisconnectOnUnload = fonction setSyncDisconnectOnUnload (valeur) setOption ('sync disconnect on unload', valeur, 'boolean'); ; this.setAutoConnect = fonction setAutoConnect (valeur) setOption ('auto connect', valeur, 'boolean'); ; this.setFlashPolicyPort = fonction setFlashPolicyPort (valeur) setOption ('port de règle flash', valeur, 'nombre'); this.setForceNewConnection = fonction setForceNewConnection (valeur) setOption ('forcer une nouvelle connexion', valeur, 'boolean'); ;
Vous pouvez le remplacer par un seul setOption ()
méthode, mais il semble plus facile de taper le nom de l'option en cas de chameau, plutôt que de le transmettre sous forme de chaîne avec des espaces.
Cette fonction créera l'objet de service que nous pourrons utiliser plus tard (par exemple dans les contrôleurs). D'abord, appelons le io ()
fonction pour se connecter au serveur Socket.IO:
ceci. $ get = fonction $ socketFactory ($ rootScope) var socket = io (ioUrl, ioConfig);
Notez que nous assignons la fonction à la $ get
propriété de l’objet créé par le fournisseur - c’est important car AngularJS utilise cette propriété pour l’appeler. Nous avons aussi mis $ rootScope
comme paramètre. À ce stade, nous pouvons utiliser l'injection de dépendance d'AngularJS pour accéder à d'autres services. Nous allons l'utiliser pour propager les modifications à tous les modèles dans les rappels Socket.IO.
Maintenant, la fonction doit retourner un objet:
revenir ; ;
Nous y mettrons toutes les méthodes pour le service.
sur()
MéthodeCette méthode attachera un écouteur d'événement à l'objet socket afin que nous puissions utiliser toutes les données envoyées depuis le serveur:
on: fonction on (événement, rappel)
Nous allons utiliser Socket.IO socket.on ()
attacher notre rappel et l'appeler dans AngularJS $ scope. $ apply ()
méthode. C'est très important, car les modèles ne peuvent être modifiés qu'à l'intérieur:
socket.on (événement, fonction ()
Tout d'abord, nous devons copier les arguments dans une variable temporaire pour pouvoir les utiliser plus tard. Les arguments sont bien sûr tout ce que le serveur nous a envoyé:
var args = arguments;
Ensuite, nous pouvons appeler notre rappel en utilisant Function.apply ()
pour lui passer des arguments:
$ rootScope. $ apply (function () callback.apply (socket, args);); ); ,
Quand prise
L'émetteur d'événements appelle la fonction d'écoute qu'il utilise $ rootScope. $ apply ()
d'appeler le rappel fourni comme deuxième argument du .sur()
méthode. De cette façon, vous pouvez écrire vos écouteurs d'événements comme vous le feriez pour n'importe quelle autre application utilisant Socket.IO, mais vous pouvez également modifier les modèles AngularJS..
de()
MéthodeCette méthode supprimera un ou tous les écouteurs d'événement pour un événement donné. Cela vous aide à éviter les fuites de mémoire et les comportements inattendus. Imaginez que vous utilisez ngRoute
et vous attachez quelques auditeurs dans chaque contrôleur. Si l'utilisateur accède à une autre vue, votre contrôleur est détruit, mais l'écouteur d'événements reste attaché. Après quelques navigations et nous aurons une fuite de mémoire.
off: fonction off (événement, rappel)
Il suffit de vérifier si le rappeler
a été fourni et appel socket.removeListener ()
ou socket.removeAllListeners ()
:
if (typeof callback == 'fonction') socket.removeListener (event, callback); else socket.removeAllListeners (event); ,
émettre()
MéthodeC'est la dernière méthode dont nous avons besoin. Comme son nom l'indique, cette méthode enverra des données au serveur:
emit: fonction emit (événement, données, rappel)
Socket.IO prenant en charge les accusés de réception, nous vérifierons si le rappeler
a été fourni. Si c'était le cas, nous utiliserons le même schéma que dans le sur()
méthode pour appeler le rappel à l'intérieur de $ scope. $ apply ()
:
if (typeof callback == 'function') socket.emit (event, data, function () var args = arguments; $ rootScope. $ apply (function () callback.apply (socket, args);); );
Si il n'y a pas rappeler
nous pouvons simplement appeler socket.emit ()
:
else socket.emit (événement, données);
Pour tester la bibliothèque, nous allons créer un formulaire simple qui enverra des données au serveur et affichera la réponse. Tout le code JavaScript de cette section doit être placé dans la >