Heim  >  Artikel  >  Web-Frontend  >  Ausführliche Erklärung von Node.js: Events-Ereignismodul

Ausführliche Erklärung von Node.js: Events-Ereignismodul

高洛峰
高洛峰Original
2016-12-05 13:37:131504Durchsuche

Die meisten Kern-APIs von Nodejs basieren auf asynchronem ereignisgesteuertem Design und alle Objekte, die Ereignisse verteilen können, sind Instanzen der EventEmitter-Klasse.

Da wir alle wissen, dass NodeJS in einem einzelnen Thread ausgeführt wird, muss NodeJS Ereignisabfragen verwenden, um Ereignisnachrichten in der Ereigniswarteschlange kontinuierlich abzufragen, und dann die dem Ereignis entsprechende Rückruffunktion ausführen ähnelt in gewisser Weise dem Windows-Meldungszuordnungsmechanismus. Detailliertere Implementierungslinks finden Sie separat.

Im Folgenden wird die Verwendung von EventEmitter vorgestellt.

1. Auf Ereignisse warten und Ereignisse verteilen

EventEmitter-Instanzen können on oder addListener verwenden, um auf Ereignisse zu warten, und die Methode emit() verteilt Ereignisse, wie unten gezeigt:

const events = require('events'),
   EventEmitter = events.EventEmitter,
   util = require('util');
function myEmiter(){
  EventEmitter.call(this);
};
util.inherits(myEmiter,EventEmitter);//继承EventEmitter类
const myEmitterIns = new myEmiter();
myEmitterIns.on('data',(o)=>{
  console.log('receive the data:'+o.a);
});

oder Klasse verwenden

class myEmiter extends EventEmitter{}//继承EventEmitter类
const myEmitterIns = new myEmiter();
 
myEmitterIns.on('data',(o)=>{
  console.log('receive the data:'+o.a);
});
myEmitterIns.emit('data',{a:1});

Das Ausführungsergebnis ist wie folgt:

E :developmentdocumentnodejsdemo>node event-example.js
empfangen Sie die Daten:1

2. Übergeben Sie Parameter an die Event-Listening-Callback-Funktion

As Aus dem obigen Beispiel ist ersichtlich, dass die Methode „emit“ einen beliebigen Parametersatz an die Rückruffunktion übergeben kann. Zu beachten ist, dass das Schlüsselwort „this“ auf die EventEmiter-Instanz verweist, die die Methode „emit“ aufruft Pfeilfunktion Dies zeigt auf das globale Dies, da dies in der Pfeilfunktion zum Definitionszeitpunkt gebunden ist. Wie unten gezeigt:

class myEmiter extends EventEmitter{}
const myEmitterIns = new myEmiter();
myEmitterIns.on('data',function(data){
  console.log("普通回调函数中this:");
  console.log(this);
});
myEmitterIns.on('data1',(data1)=>{
  console.log("箭头回调函数中this:");
  console.log(this);
});
myEmitterIns.emit('data',{a:1});
myEmitterIns.emit('data1',{a:1});

Das Ausführungsergebnis ist wie folgt:

E:developmentdocumentnodejsdemo>node event-example.js
Gewöhnlicher Rückruf Dies in der Funktion:
myEmiter {
domain: null,
_events: { data: [Function], data1: [Function] },
_eventsCount: 2,
_maxListeners : undefiniert }
Dies in der Pfeil-Callback-Funktion:
{}

Hier sprechen wir darüber in der Pfeilfunktion. Übrigens, warum die Pfeilfunktion dies binden kann, wenn sie definiert ist weil die internen Grundlagen der Pfeilfunktion Es gibt keinen Mechanismus, um dies zu binden Es verwendet dies aus dem äußeren Bereich und kann daher nicht als Konstruktor verwendet werden.

3. Ausführungssequenz von Ereignis-Listenern

Die EventEmiter-Instanz kann mehrere Ereignisse nacheinander binden. EventEmiter wird im synchronen Modus ausgeführt, d. h. zuerst Wenn die Verarbeitungsfunktion nicht abgeschlossen ist, wird das nächste Ereignis nicht ausgelöst, wie unten gezeigt:

class myEmiter extends EventEmitter{}
const myEmitterIns = new myEmiter();
myEmitterIns.on('data',function(data){
  console.time('data事件执行了');
  for(var i = 0 ; i< 100000; i++)
    for(var j = 0 ; j< 100000; j++)
      ;
  console.timeEnd(&#39;data事件执行了&#39;);
});
myEmitterIns.on(&#39;data1&#39;,(data1)=>{
  console.log("data1事件开始执行...");
});
myEmitterIns.emit(&#39;data&#39;,{a:1});
myEmitterIns.emit(&#39;data1&#39;,{a:1});

Das Ausführungsergebnis lautet wie folgt:

E:developmentdocumentnodejsdemo>node event-example.js
Das Datenereignis wurde ausgeführt: 4721,401 ms
Die Ausführung des Daten1-Ereignisses wurde gestartet...

Natürlich können wir asynchrone Operationen im verwenden Rückruffunktionen wie setTimeout, setImmediate oder process.nextTick() usw., um asynchrone Effekte zu erzielen, wie unten gezeigt:

myEmitterIns.on(&#39;data&#39;,function(data){
  setImmediate(()=>{
    console.log(&#39;data事件执行了...&#39;);
  });
});

Die Ausführung Die Ergebnisse lauten wie folgt:

E:developmentdocumentnodejsdemo>node event-example.js
data1-Ereignis wurde ausgeführt...
Datenereignis wurde ausgeführt...

Eins -Zeit-Ereignisüberwachung

EventEmiter kann einmal zum Abhören eines Ereignisses verwendet werden, und der Ereignishandler wird nur einmal ausgelöst. Danach wird das Ereignis ignoriert, da der Zuhörer abgemeldet ist, wie gezeigt unten:

myEmitterIns.once(&#39;one&#39;,(data)=>{
  console.log(data);
});
myEmitterIns.emit(&#39;one&#39;,&#39;this is first call!&#39;);
myEmitterIns.emit(&#39;one&#39;,&#39;this is second call!&#39;);

Die Ausführungsergebnisse sind wie folgt:

E:developmentdocumentnodejsdemo>node event-example.js
this ist der erste Aufruf!

Wie aus den obigen Ergebnissen ersichtlich ist, wird das Ereignis „eins“ nur einmal ausgeführt.

5. Ereignisbindung entfernen

Ähnlich wie bei der DOM-Ereignisüberwachung kann EventEmiter auch die Ereignisbindung entfernen und die Methode „removeListener(eventName,listener)“ verwenden, um die Bindung eines Ereignisses aufzuheben. Daher muss der Listener der Rückruffunktion eine benannte Funktion sein. Andernfalls kann die Funktion nicht gefunden werden, da die Funktion ein Referenztyp ist. Auch wenn der Funktionskörper identisch ist, handelt es sich nicht um dieselbe Funktion, wie unten gezeigt:

myEmitterIns.on(&#39;data&#39;,function(e){
  console.log(e);
});
myEmitterIns.removeListener(&#39;data&#39;,function(e){
  console.log(e);
});
myEmitterIns.emit(&#39;data&#39;,&#39;hello data!&#39;);
function deal(e){
  console.log(e);
}
myEmitterIns.on(&#39;data1&#39;,deal);
myEmitterIns.removeListener(&#39;data1&#39;,deal);
myEmitterIns.emit(&#39;data1&#39;,&#39;hello data1!&#39;);

Die Ausführungsergebnisse lauten wie folgt:

E:developmentdocumentnodejsdemo>node event-example.js
Hallo Daten!
E :developmentdocumentnodejsdemo>

Aus den Ausführungsergebnissen ist ersichtlich, dass das Datenereignis eine anonyme Funktion verwendet und daher nicht entfernt wird, während das Daten1-Ereignis erfolgreich entbunden wurde. Hierbei ist zu beachten, dass nach dem Auslösen eines Ereignisses durch emit alle an das Ereignis gebundenen Rückruffunktionen aufgerufen werden. Selbst wenn Sie die Funktion „removeListener“ in einer Rückruffunktion verwenden, um einen anderen Rückruf zu entfernen, ist dies nutzlos, aber die Ereigniswarteschlange ist nachfolgend hat den Rückruf entfernt. Wie unten gezeigt:

function dealData1(e){
  console.log(&#39;data事件执行了...A&#39;);
}
myEmitterIns.on(&#39;data&#39;,function(e){
  console.log(e);
  myEmitterIns.removeListener(&#39;data&#39;,dealData1);//这里解除dealData1的绑定
});
myEmitterIns.on(&#39;data&#39;,dealData1);
myEmitterIns.emit(&#39;data&#39;,&#39;data事件执行了...B&#39;);
/*执行结果为:
 data事件执行了...B
 data事件执行了...A
*/
//再次触发该事件时,dealData1回调已经被解除绑定了
myEmitterIns.emit(&#39;data&#39;,&#39;data事件执行了...&#39;);
//data事件执行了...
   
另外可以使用removeAllListeners()解除所有事件的绑定。

6. Ermitteln Sie die Anzahl der Ereignis-Listener und die Listener-Funktion.

Verwenden Sie die Funktion emitter.listenerCount(eventName), um die Anzahl der Listener zu ermitteln Das angegebene Ereignis und die Funktion emitter.listeners (eventName) können verwendet werden, um alle Abhörfunktionen des angegebenen Ereignisses wie folgt abzurufen:

var cbA = ()=>{},
  cbB = ()=>{};
var emitter = new myEmiter();
emitter.on(&#39;data&#39;,cbA);
emitter.on(&#39;data&#39;,cbB);
console.log(&#39;emitter实例的data事件绑定了%d个回调函数&#39;,emitter.listenerCount(&#39;data&#39;));
console.log(&#39;它们是:&#39;,emitter.listeners(&#39;data&#39;));

Das Ausführungsergebnis lautet wie folgt:

E:developmentdocumentnodejsdemo>node event-example.js
Das Datenereignis der Emitter-Instanz ist an 2 Rückruffunktionen gebunden
Sie sind: [ [Funktion: cbA ], [Funktion: cbB] ]

7. Holen Sie sich die maximale Anzahl von Emitter-Listenern und legen Sie sie fest
Nodejs empfiehlt, dass die Anzahl der Listener für dasselbe Ereignis 10 nicht überschreiten sollte. Dies kann durch ermittelt werden Anzeigen der EventEmitter.defaultMaxListeners-Eigenschaft, wie unten gezeigt:

console.log(EventEmitter.defaultMaxListeners);//结果为10个

Emitter erhält die maximale Anzahl von Listenern über die Methode getMaxListeners() und legt die maximale Anzahl fest von Listenern über die setMaxListeners(n)-Methode, wie unten gezeigt:

var cbA = ()=>{},
  cbB = ()=>{};
var emitter = new myEmiter();
emitter.setMaxListeners(1);
emitter.on(&#39;data&#39;,cbA);
emitter.on(&#39;data&#39;,cbB);
console.log(emitter.getMaxListeners());

Die Ausführungsergebnisse lauten wie folgt:

E:developmentdocumentnodejsdemo>node event-example.js
Die maximale Anzahl von Emitter-Ereignis-Listenern beträgt: 1
(node:6808) Warnung: Möglich EventEmitter-Speicherleck erkannt. 2 Daten-Listener werden hinzugefügt. Verwenden Sie emitter.setMaxListeners(), um das Limit zu erhöhen. Wie in den obigen Ergebnissen gezeigt, ist es am besten, dies nicht zu tun Überschreiten Sie die maximale Anzahl von Listenern für dasselbe Ereignis. Andernfalls wird wahrscheinlich ein Speicherverlust gesendet.

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn