Utilisation du module d'événements du nœud

Lorsque j'ai entendu parler de Node.js pour la première fois, j'ai pensé qu'il ne s'agissait que d'une implémentation JavaScript pour le serveur. Mais c’est bien plus que cela: il est livré avec une foule de fonctions intégrées que vous n’aurez pas dans le navigateur. Une de ces fonctionnalités est le module d’événement, qui a la EventEmitter classe. Nous allons regarder cela dans ce tutoriel.


EventEmitter: Quoi et pourquoi

Alors, que fait exactement le EventEmitter classe faire? En termes simples, cela vous permet d’écouter des "événements" et d’affecter des actions à exécuter lorsque ces événements se produisent. Si vous connaissez le JavaScript frontal, vous saurez tout sur les événements de souris et de clavier qui se produisent lors de certaines interactions utilisateur. Celles-ci sont très similaires, sauf que nous pouvons émettre des événements nous-mêmes, quand nous le voulons, et pas nécessairement en fonction de l’interaction de l’utilisateur. Les principes EventEmitter s'appuie sur le modèle de publication / abonnement, car nous pouvons nous abonner à des événements, puis les publier. Il existe de nombreuses bibliothèques frontales construites avec le support pub / sub, mais Node l’a construit.

L'autre question importante est la suivante: pourquoi utiliseriez-vous le modèle d'événement? Dans Node, il s'agit d'une alternative aux rappels profondément imbriqués. De nombreuses méthodes de nœud sont exécutées de manière asynchrone, ce qui signifie que pour exécuter du code une fois la méthode terminée, vous devez passer une méthode de rappel à la fonction. Finalement, votre code ressemblera à un entonnoir géant. Pour éviter cela, de nombreuses classes de nœuds émettent des événements que vous pouvez écouter. Cela vous permet d'organiser votre code comme vous le souhaitez et de ne pas utiliser de rappels..

Un dernier avantage pour les événements: ils constituent un moyen très souple de coupler des parties de votre code. Un événement peut être émis, mais si aucun code ne l’écoute, c’est normal: il passera inaperçu. Cela signifie que la suppression des écouteurs (ou des émissions d'événements) ne génère jamais d'erreurs JavaScript..


En utilisant EventEmitter

Nous allons commencer par le EventEmitter classe seule. Il est assez simple de se rendre à: nous avons simplement besoin du module events:

 var events = require ("events");

Ce événements objet a une seule propriété, qui est la EventEmitter classe elle-même. Alors, faisons un exemple simple pour les débutants:

 var EventEmitter = require ("events"). EventEmitter; var ee = new EventEmitter (); ee.on ("someEvent", function () console.log ("un événement est survenu");); ee.emit ("someEvent");

Nous commençons par créer un nouveau EventEmitter objet. Cet objet a deux méthodes principales que nous utilisons pour les événements: sur et émettre.

Nous commençons par sur. Cette méthode prend deux paramètres: nous commençons par le nom de l'événement que nous écoutons: dans ce cas, c'est "un événement". Mais bien sûr, cela pourrait être n'importe quoi et vous choisirez généralement quelque chose de mieux. Le deuxième paramètre est la fonction qui sera appelée lorsque l'événement se produit. C'est tout ce qui est nécessaire pour organiser un événement.

Maintenant, pour déclencher l'événement, vous transmettez le nom de l'événement au EventEmitter les instances émettre méthode. C'est la dernière ligne du code ci-dessus. Si vous exécutez ce code, vous verrez que le texte est imprimé sur la console..

C'est l'utilisation la plus élémentaire d'un EventEmitter. Vous pouvez également inclure des données lors du déclenchement d'événements:

 ee.emit ("nouvel utilisateur", userObj);

Ce n'est qu'un paramètre de données, mais vous pouvez en inclure autant que vous le souhaitez. Pour les utiliser dans votre fonction de gestionnaire d’événements, il suffit de les prendre comme paramètres:

 ee.on ("nouvel utilisateur", function (data) // utiliser les données ici);

Avant de continuer, permettez-moi de clarifier une partie de la EventEmitter fonctionnalité. Nous pouvons avoir plus d'un auditeur pour chaque événement; plusieurs écouteurs d'événements peuvent être assignés (tous avec sur) et toutes les fonctions seront appelées lors du déclenchement de l’événement. Par défaut, Node autorise jusqu'à dix auditeurs sur un événement à la fois. si plus sont créés, le noeud émettra un avertissement. Cependant, nous pouvons changer ce montant en utilisant setMaxListeners. Par exemple, si vous exécutez ceci, vous devriez voir un avertissement imprimé au-dessus de la sortie:

 ee.on ("someEvent", function () console.log ("event 1");); ee.on ("someEvent", function () console.log ("event 2");); ee.on ("someEvent", function () console.log ("event 3");); ee.on ("someEvent", function () console.log ("event 4");); ee.on ("someEvent", function () console.log ("event 5");); ee.on ("someEvent", function () console.log ("event 6");); ee.on ("someEvent", function () console.log ("event 7");); ee.on ("someEvent", function () console.log ("event 8");); ee.on ("someEvent", function () console.log ("event 9");); ee.on ("someEvent", function () console.log ("event 10");); ee.on ("someEvent", function () console.log ("event 11");); ee.emit ("someEvent");

Pour définir le nombre maximal de téléspectateurs, ajoutez cette ligne au-dessus des écouteurs:

 ee.setMaxListeners (20);

Maintenant, quand vous l'exécutez, vous ne recevrez pas d'avertissement.


Autre EventEmitter Les méthodes

Il y a quelques autres EventEmitter méthodes que vous trouverez utiles.

En voici une soignée: une fois que. C'est comme le sur méthode, sauf que cela ne fonctionne qu'une fois. Après avoir été appelé pour la première fois, l'auditeur est supprimé.

 ee.once ("firstConnection", function () console.log ("Vous ne verrez plus jamais cela");); ee.emit ("firstConnection"); ee.emit ("firstConnection");

Si vous exécutez ceci, vous ne verrez le message qu'une seule fois. La deuxième émission de l’événement n’a pas été écoutée par les auditeurs (et c’est bien, au fait), car le une fois que l'auditeur a été retiré après avoir été utilisé une fois.

En parlant d'éliminer les auditeurs, nous pouvons le faire nous-mêmes, manuellement, de plusieurs manières. Tout d'abord, nous pouvons supprimer un seul auditeur avec le removeListener méthode. Il faut deux paramètres: le nom de l'événement et la fonction d'écoute. Jusqu'ici, nous avons utilisé des fonctions anonymes en tant qu'auditeurs. Si nous voulons être en mesure de supprimer un écouteur plus tard, il faudra une fonction avec un nom que nous pouvons référencer. Nous pouvons utiliser ceci removeListener méthode pour reproduire les effets de la une fois que méthode:

 function onlyOnce () console.log ("Vous ne verrez plus jamais cela"); ee.removeListener ("firstConnection", onlyOnce);  ee.on ("firstConnection", onlyOnce) ee.emit ("firstConnection"); ee.emit ("firstConnection");

Si vous exécutez ceci, vous verrez que cela a le même effet que une fois que.

Si vous souhaitez supprimer tous les écouteurs liés à un événement donné, vous pouvez utiliser removeAllListeners; il suffit de lui passer le nom de l'événement:

 ee.removeAllListeners ("firstConnection");

Pour supprimer tous les écouteurs de tous les événements, appelez la fonction sans paramètre..

ee.removeAllListeners ();

Il y a une dernière méthode: auditeur. Cette méthode prend un nom d'événement en tant que paramètre et renvoie un tableau de toutes les fonctions à l'écoute de cet événement. Voici un exemple de cela, basé sur notre juste une fois Exemple:

 function onlyOnce () console.log (ee.listeners ("firstConnection")); ee.removeListener ("firstConnection", onlyOnce); console.log (ee.listeners ("firstConnection"));  ee.on ("firstConnection", onlyOnce) ee.emit ("firstConnection"); ee.emit ("firstConnection");

Nous terminerons cette section avec un peu de méta-nessité. Notre EventEmitter L’instance elle-même déclenche en réalité deux événements que nous pouvons écouter: l’un lorsque nous créons de nouveaux écouteurs et l’autre lorsque nous les supprimons. Vois ici:

 ee.on ("newListener", fonction (evtName, fn) console.log ("New Listener:" + evtName);); ee.on ("removeListener", function (evtName) console.log ("Listener supprimé:" + evtName);); fonction foo ()  ee.on ("save-user", foo); ee.removeListener ("save-user", foo);

En cours d'exécution, vous verrez que nos auditeurs à la fois pour les nouveaux auditeurs et les auditeurs supprimés ont été exécutés, et nous recevons les messages que nous attendions..

Alors, maintenant que nous avons vu toutes les méthodes qui un EventEmitter par exemple, voyons comment cela fonctionne en conjonction avec d'autres modules.

EventEmitter Modules intérieurs

Depuis le EventEmitter class est juste du code JavaScript ordinaire, il est donc parfaitement logique qu’il puisse être utilisé dans d’autres modules. Dans vos propres modules JavaScript, vous pouvez créer EventEmitter instances, et les utiliser pour gérer des événements internes. C'est simple, cependant. Plus intéressant, serait de créer un module qui hérite de EventEmitter, afin que nous puissions utiliser sa partie fonctionnalité de l'API publique.

En fait, il existe des modules de nœud intégrés qui font exactement cela. Par exemple, vous connaissez peut-être le http module; C'est le module que vous utiliserez pour créer un serveur Web. Cet exemple de base montre comment le sur méthode du EventEmitter la classe est devenue une partie de la http.Server classe:

 var http = require ("http"); var server = http.createServer (); server.on ("request", fonction (req, res) res.end ("c'est la réponse");); server.listen (3000);

Si vous exécutez cet extrait, le processus attendra une demande. tu peux aller à http: // localhost: 3000 et vous aurez la réponse. Lorsque l’instance de serveur reçoit la demande de votre navigateur, elle émet une "demande" événement, un événement que notre auditeur recevra et pourra agir.

Alors, comment pouvons-nous créer une classe qui héritera de EventEmitter? Ce n'est pas si difficile. Nous allons créer un simple Liste d'utilisateur classe, qui gère les objets utilisateur. Donc, dans un userlist.js fichier, nous allons commencer par ceci:

 var util = require ("util"); var EventEmitter = require ("events"). EventEmitter;

Nous avons besoin de util module pour aider avec l'héritage. Ensuite, nous avons besoin d’une base de données: au lieu d’utiliser une base de données réelle, nous utiliserons simplement un objet:

 var id = 1; var database = utilisateurs: [id: id ++, nom: "Joe Smith", profession: "développeur", id: id ++, nom: "Jane Doe", profession: "analyste de données", id: id ++ , nom: "John Henry", profession: "designer"];

Nous pouvons maintenant créer notre module. Si vous ne connaissez pas bien les modules Node, voici comment ils fonctionnent: tout code JavaScript que nous écrivons dans ce fichier est uniquement lisible à partir de l'intérieur du fichier, par défaut. Si nous voulons en faire une partie de l'API publique du module, nous en faisons une propriété de module.exports, ou assigner un nouvel objet ou une fonction à module.exports. Faisons cela:

 function UserList () EventEmitter.call (this); 

C'est la fonction constructeur, mais ce n'est pas votre fonction constructeur JavaScript habituelle. Ce que nous faisons ici utilise le appel méthode sur le EventEmitter constructeur pour exécuter cette méthode sur le nouveau Liste d'utilisateur objet (qui est ce). Si nous avons besoin de faire une autre initialisation avec notre objet, nous pourrions le faire dans cette fonction, mais c'est tout ce que nous ferons pour l'instant..

Hériter du constructeur ne suffit cependant pas; nous devons également hériter du prototype. C'est là que le util le module arrive.

 util.inherits (UserList, EventEmitter);

Cela va ajouter tout ce qui est sur EventEmitter.prototype à UserList.prototype; maintenant, notre Liste d'utilisateur les instances auront toutes les méthodes d'un EventEmitter exemple. Mais nous voulons ajouter un peu plus, bien sûr. Nous allons ajouter un enregistrer méthode, pour nous permettre d'ajouter de nouveaux utilisateurs.

 UserList.prototype.save = fonction (obj) obj.id = id ++; database.users.push (obj); this.emit ("utilisateur enregistré", obj); ;

Cette méthode prend un objet à enregistrer dans notre "base de données": il ajoute un identifiant et le pousse dans le tableau d'utilisateurs. Ensuite, il émet le "utilisateur enregistré" événement, et passe l'objet en tant que données. S'il s'agissait d'une vraie base de données, l'enregistrement serait probablement une tâche asynchrone, ce qui signifie que pour utiliser l'enregistrement sauvegardé, nous aurions besoin d'accepter un rappel. L'alternative à cela est d'émettre un événement, comme nous le faisons. Maintenant, si nous voulons faire quelque chose avec l'enregistrement sauvegardé, nous pouvons simplement écouter l'événement. Nous ferons cela dans une seconde. Il suffit de fermer la Liste d'utilisateur

 UserList.prototype.all = function () return database.users; ; module.exports = UserList;

J'ai ajouté une méthode supplémentaire: une méthode simple qui renvoie tous les utilisateurs. Ensuite, nous assignons Liste d'utilisateur à module.exports.

Voyons maintenant ceci en cours d'utilisation. dans un autre fichier, disons test.js. Ajouter ce qui suit:

 var UserList = require ("./ userlist"); var users = new UserList (); utilisateurs.on ("utilisateur enregistré", fonction (utilisateur) console.log ("enregistré:" + utilisateur.nom + "(" + utilisateur.id + ")"); users.save (name: "Jane Doe", profession: "manager"); utilisateurs.save (nom: "John Jacob", profession: "développeur");

Après avoir requis notre nouveau module et créé une instance de celui-ci, nous écoutons les "utilisateur enregistré" un événement. Ensuite, nous pouvons sauver quelques utilisateurs. Lorsque nous exécuterons cela, vous verrez que nous recevons deux messages, imprimant les noms et identifiants des enregistrements que nous avons enregistrés..

 sauvé: Jane Doe (4) sauvé: John Jacob (5)

Bien sûr, cela pourrait fonctionner dans le sens inverse: nous pourrions utiliser le sur méthode de l'intérieur de notre classe et la émettre méthode à l'extérieur, ou les deux à l'intérieur ou à l'extérieur. Mais c’est un bon exemple de la façon dont cela pourrait être fait.


Conclusion

Voilà donc comment Node's EventEmitter travaux de classe. Vous trouverez ci-dessous des liens vers la documentation sur les nœuds pour certaines des choses dont nous avons parlé.

  • Module d'événements de nœud
  • Node Util Module
  • Node HTTP Agent Source - Affiche le modèle d'héritage utilisé.