Maison >interface Web >js tutoriel >Explication du mécanisme d'événement de nœud

Explication du mécanisme d'événement de nœud

小云云
小云云original
2018-01-26 13:31:341509parcourir

Cet article présente principalement le mécanisme d'événement de node. Cet article implémente un mécanisme d'événement simple avec mode publication/abonnement pour clarifier les idées d'implémentation de la classe EventEmitter. Ceux qui sont intéressés pourront en apprendre davantage. Tout le monde.

Node.js utilise un modèle d'E/S non bloquant et piloté par les événements qui le rend léger et efficace.

Dans la documentation officielle de nodejs, il est clairement écrit L'une des fonctionnalités de node est pilotée par les événements, ce qui montre qu'elle est très importante. En regardant le code source, nous pouvons voir que son mécanisme d'événement est la classe EventEmitter écrite en js, qui est écrite de manière très élégante et applique le modèle de publication/abonnement.

En implémentant un mécanisme d'événement simple avec le mode publication/abonnement, nous pouvons clarifier les idées d'implémentation de la classe EventEmitter

Publish/Subscribe (mode publication/abonnement)

L'analogie

concerne un modèle, et le mot modèle semble très abstrait. Donnons d’abord une châtaigne. Supposons qu'il existe une organisation de presse qui propose des journaux du matin, de l'après-midi et du soir. Si vous souhaitez lire un certain journal, vous devez vous abonner à l'organisation du journal. Lorsque le journal correspondant sera publié, l'organisation du journal vous demandera de récupérer le journal.

Dans ce processus, l'organisation du journal met en œuvre deux fonctions, l'une consiste à accepter les abonnements des clients ; l'autre est de publier différents types de journaux. Lorsqu'un journal est publié, les clients abonnés à ce type de journal recevront des notifications.

Cette organisation de journal est le mécanisme événementiel que nous souhaitons mettre en place.

Objectif

Comme le montre l'exemple ci-dessus : 1. Publier le journal 2. Donner le journal au ; client ; ceci En raison de l'existence de l'organisation du journal, le processus continu peut d'abord être souscrit puis publié lorsqu'il est publié, il sera automatiquement envoyé au client, réalisant ainsi la séparation du temps d'action. C’est aussi l’avantage des systèmes de publication/abonnement.

Idées de mise en œuvre

Nous avons 3 types de journaux, correspondant à 3 événements, et les clients doivent être avertis lorsque chaque événement se produit. Le format de données correspondant peut être le suivant :


var Event = {
 morning: event1,
 noon: event2,
 night: event3
}

Comme chaque journal peut être abonné par plus d'une personne, le format peut être optimisé comme ceci :


var Event = {
 morning: [e11, e12,...],
 noon: [e21, e22],
 night: event3
}

Lorsqu'un utilisateur s'abonne, on ajoute son événement au tableau correspondant ; lorsque l'événement est publié, l'événement correspondant est exécuté. Pour parler franchement, stockez-le d’abord, puis utilisez-le.

Le code spécifique est le suivant :

1.on signifie s'abonner, ajouter l'événement au tableau correspondant
2.emit signifie publier, ajouter les données dans le tableau correspondant Retirez-le et exécutez
3.off pour supprimer les événements inutiles


var Event = {
 on: function(key, listener) {
  if (!this.__events) {
   this.__events = {}
  }
  if (!this.__events[key]) {
   this.__events[key] = [];
  } 
  if (_indexOf(this.__events[key], listener) == -1 && typeof listener === 'function') {
   this.__events[key].push(listener)
  }
 },
 emit: function(key) {
  if (!this.__events || !this.__events[key]) return 
  //取得每次订阅不同的参数
  var arg = Array.prototype.slice.call(arguments, 1) || [];

  var listeners = this.__events[key];
  var len = listeners.length;

  for (var i=0; i<len; i++) {
   listeners[i].apply(this, arg)
  }
  return this

 },
 off: function(key, listener) {
  if (!key && !listener) {
   this.__events = {}
  }
  if (key && !listener) {
   delete this.__events[key]
  }
  if (key && listener) {
   var listeners = this.__events[key];
   var index = _indexOf(listeners, listener);
   (index > -1) && listeners.splice(index, 1);
  }
  return this
 }
}

var _indexOf = function(array,key){
 if (array === null) return -1
 var i = 0, length = array.length
 for (; i < length; i++) if (array[i] === key) return i
 return -1
}
//调用
Event.on(&#39;console1&#39;, function(num) {
 console.log(num); // 1
});

Event.emit(&#39;console1&#39;, 1)

EventEmitter of node

EventEmitter of node La logique de base est fondamentalement la même que celle de l'exemple fourni ci-dessus, juste plus compliquée.

1. Abonnez-vous aux événements sur


function _addListener(target, type, listener, prepend) {
 var m;
 var events;
 var existing;

 if (typeof listener !== &#39;function&#39;)
  throw new TypeError(&#39;"listener" argument must be a function&#39;);

 events = target._events;
 ...
 if (typeof existing === &#39;function&#39;) {
   // Adding the second element, need to change to array.
   existing = events[type] =
    prepend ? [listener, existing] : [existing, listener];
  } else {
   // If we&#39;ve already got an array, just append.
   if (prepend) {
    existing.unshift(listener);
   } else {
    existing.push(listener);
   }
  }

 return target;
}

EventEmitter.prototype.addListener = function addListener(type, listener) {
 return _addListener(this, type, listener, false);
};

EventEmitter.prototype.on = EventEmitter.prototype.addListener;

2. Publier des événements


EventEmitter.prototype.emit = function emit(type) {
 ...
 handler = events[type];
 switch (len) {
  // fast cases
  case 1:
   emitNone(handler, isFn, this);
   break;
  case 2:
   emitOne(handler, isFn, this, arguments[1]);
   break;
  case 3:
   emitTwo(handler, isFn, this, arguments[1], arguments[2]);
   break;
  case 4:
   emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]);
   break;
  // slower
  default:
   args = new Array(len - 1);
   for (i = 1; i < len; i++)
    args[i - 1] = arguments[i];
   emitMany(handler, isFn, this, args);
 }
}

À ce stade, je pense que tout le monde comprend déjà l'idée de mise en œuvre d'EventEmitter.

Recommandations associées :

Mise en œuvre du mécanisme d'événement PHP

Mécanisme d'événement et blocage en jq et js

Mécanisme d'événements JavaScript

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn