Novice à node.js, quel est l'avantage obtenu en utilisant les rappels sur les événements?

24

Je suis un JavaScripter novice et je n'ai aucune connaissance réelle de ce qui se passe à l'intérieur du moteur V8.

Cela dit, j'apprécie vraiment mes premières incursions dans l'environnement node.js, mais je trouve que j'utilise constamment events.EventEmitter () comme moyen d'émettre des événements globaux afin de pouvoir structurer mes programmes en fonction d'un notificateur-observateur modèle similaire à ce que j'écrirais, par exemple un programme Objective-C ou Python.

Je me retrouve toujours à faire des choses comme ça:

var events = require('events');

var eventCenter = new events.EventEmitter();

eventCenter.on('init', function() {
    var greeting = 'Hello World!';
    console.log('We're in the init function!);
    eventCenter.emit('secondFunction', greeting);
});

eventCenter.on('secondFunction', function(greeting) {
        console.log('We're in the second function!);
        console.log(greeting);
    eventCenter.emit('nextFunction');
});

eventCenter.on('nextFunction', function {
    /* do stuff */
});

eventCenter.emit('init');

Donc, en fait, je suis juste en train de structurer le code node.js 'async' en un code qui fait les choses dans l'ordre que j'attends, au lieu de cela je suis plutôt en train de "coder à l'envers" si cela a du sens. Y aurait-il une différence à le faire de manière intensive, que ce soit en termes de performances ou de philosophie? Est-il préférable de faire la même chose en utilisant des rappels au lieu d'événements?

Faire du jogging
la source
Si vous trouvez que votre lisibilité du code souffre en raison d'une utilisation intensive des rappels, envisagez d'utiliser un cadre pour encapsuler votre utilisation des rappels. Cela prend un peu d'ajustement, mais les promesses peuvent souvent démêler les rappels laids. Si vous utilisez JQuery, vous pouvez utiliser différé . RSVP est l'un des cadres de promesse les plus simples .
Brian
Je suis confus, je ne vois rien d'asynchrone dans votre code, juste des appels de fonction écrits d'une manière trop compliquée.
svick

Réponses:

27

La bonne chose à propos des rappels est qu'il n'y a pas d'état global là-bas, et leur transmettre des paramètres est trivial. Si vous avez une fonction, download(URL, callback: (FileData)->void)vous pouvez savoir que c'est une fonction autonome d'ordre supérieur qui vous permet essentiellement de construire une fonction "saisir ceci et faire cela". Vous pouvez être sûr que votre flux de code est exactement ce que vous attendez, car personne d'autre n'a même une poignée sur ce rappel, et ce rappel ne sait rien d'autre que les paramètres donnés de la fonction parent. Cela le rend modulaire et facile à tester.

Si vous souhaitez maintenant télécharger 5 fichiers en parallèle et faire des choses différentes, vous n'avez qu'à déclencher cinq de ces fonctions avec les fonctions de rappel appropriées. Dans un langage avec une bonne syntaxe de fonction anonyme, cela peut être incroyablement puissant.

Les événements, d'autre part, sont plus conçus pour informer les 1..*utilisateurs de certains changements d'état. Si vous déclenchez un événement "téléchargement terminé" à la fin de download(URL), qui lance processDownload()qui sait où trouver les données, vous liez vos implémentations de choses à une plus grande quantité d'état. Comment parallélisez-vous les téléchargements maintenant? Comment gérez-vous les différents téléchargements différemment? Est-ce download(URL, eventId)élégant? Est-ce downloadAndDoThing(URL)élégant? À peine.

Bien sûr, comme pour tout, vous faites des compromis. Callbacks emboîtées peuvent faire l'ordre d'exécution du code plus confus, et le manque de accessability global facile en fait un mauvais choix pour quoi que ce soit où vous faire une 1..*relation entre le producteur et le consommateur. Vous avez plus de mal à transmettre des données, mais si vous pouvez vous en sortir sans avoir d'état supplémentaire, c'est généralement un avantage de toute façon.

Indépendamment. Vous codez dans node.js où les rappels sont idiomatiques, et le langage et les bibliothèques sont conçus autour de leur utilisation. Que vous voyiez des avantages dans une conception ou une autre, je pense qu'il est presque toujours vrai que l'écriture de code idiomatique dans n'importe quelle langue aura un soutien beaucoup plus important et vous facilitera la vie que d'essayer de le contourner.

Phoshi
la source
2

Je n'ai jamais utilisé d'événements dans NodeJS, mais généralement ce que j'utilise pour les événements JS côté client signale que quelque chose s'est produit, par exemple un AppointmentBookedEvent, afin que différentes parties d'une vue SPA puissent réagir à cela (affichez-le dans une chronologie, chargez-le dans un panneau, etc.).
Mais utiliser des événements pour signaler qu'une méthode est terminée peut être une route dangereuse à parcourir. Vous ne pouvez pas vous fier aux événements pour arriver dans le même ordre qu'ils ont été tirés, ce qui pourrait conduire à toutes sortes d'aléatoires ...
Il n'y a rien de mal à utiliser les événements, mais il y a un certain niveau de granularité que vous ne devriez pas suivre. ; si vous vous en tenez aux événements de domaine, c'est très bien. Mais notifier que les méthodes sont terminées est trop granulaire.

Stefan Billiet
la source
0

Quelque chose que vous pourriez explorer est l'utilisation des événements en dehors de l'objet qui les émet. Dans votre exemple, eventCentersemble émettre et gérer ses propres événements. Considérez comment la structure de votre application peut changer si d'autres objets commencent à gérer les événements.

Ainsi, eventCenterpourrait émettre "init", que d'autres objets pourraient ensuite gérer pour faire leur code de démarrage, etc.

Dan1701
la source