ホームページ >ウェブフロントエンド >jsチュートリアル >Node.jsの詳細説明: eventsイベントモジュール

Node.jsの詳細説明: eventsイベントモジュール

高洛峰
高洛峰オリジナル
2016-12-05 13:37:131555ブラウズ

Nodejs のコア API のほとんどは非同期イベント駆動設計に基づいて設計されており、イベントを配布できるすべてのオブジェクトは EventEmitter クラスのインスタンスです。

ご存知のとおり、nodejs は単一のスレッドで実行されるため、nodejs はイベント ポーリングを使用してイベント キュー内のイベント メッセージを継続的にクエリし、イベントに対応するコールバック関数を実行する必要があります。これは、 Windows のメッセージ マッピング メカニズム。より詳細な実装リンクについては、別途情報を参照してください。

以下ではEventEmitterの使い方を紹介します。

1. イベントのリッスンとイベントの配布

EventEmitter インスタンスは、以下に示すように、on または addListener を使用してイベントをリッスンし、emit() メソッドを使用してイベントを配布できます。

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);
});

実行結果は次のとおりです:

E:developmentdocumentnodejsdemo>nodeevent-example.js

データを受信します:1

2. パラメータをイベントリスニングコールバック関数に渡します

上記の例からわかるように、emit() メソッドは、コールバック関数に任意のパラメータのセットを渡すことができます。注意すべき点は、this キーワードは、アロー関数を除いて、emit メソッドを呼び出す EventEmiter インスタンスをポイントしていることです。アロー関数内の this は時間バインディングが定義されているため、グローバル this に設定されます。以下に示すように:

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});


実行結果は次のとおりです:

E:developmentdocumentnodejsdemo>nodeevent-example.js

これは通常のコールバック関数内です:

myEmiter {

domain: null,

_events: { data: [Function ], data1: [Function] },

_eventsCount: 2,

_maxListeners: unknown }
this in the arrow callback function:
{}

ここで、arrow 関数でのこれについて説明します。アロー関数が実装できる理由 定義時に this をバインドするのは、アロー関数内に this をバインドする機構がないため、外側のスコープで this を使用するため、コンストラクターとして使用できません。

3. イベントリスナーの実行シーケンス

EventEmiter インスタンスは複数のイベントを連続してトリガーすることができ、最初のイベント処理関数が完了していなくても、EventEmiter は同期モードで実行されます。イベントは次のように実行されます:

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});


実行結果は次のとおりです:

E:developmentdocumentnodejsdemo>node event-example.js

data イベント実行: 4721.401ms

data1 イベントが実行を開始しました...

もちろん、以下に示すように、コールバック関数で setTimeout、setImmediate、process.nextTick() などの非同期操作を使用して、非同期効果を実現できます。

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});



実行結果は次のとおりです。 E:developmentdocumentnodejsdemo> ノードのevent-example.js

data1イベントが実行されました...

dataイベントが実行されました...

4. ワンタイムイベントモニタリング

EventEmiterはイベントをリッスンするために一度使用できます。イベント ハンドラーは 1 回だけトリガーされます。以下に示すように、リスナーがログアウトしているため、イベントは発行後に無視されます。

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



実行結果は次のとおりです。 js

this is first call!

上記の結果から、「one」イベントは 1 回だけ実行されることがわかります。

5. イベント バインディングを削除する

DOM イベント リスニングと同様に、EventEmiter もイベント バインドを解除するためにイベント バインディングを削除できるため、コールバック関数のリスナーは名前付き関数である必要があります。関数が参照型であるため、関数が見つかりません。以下に示すように、関数本体が同じであっても、同じ関数ではありません。

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;);


実行結果は次のとおりです。


E:developmentdocumentnodejsdemo>nodeevent-example.js

hello data!

E:developmentdocumentnodejsdemo>

実行結果からわかるように、data イベントは匿名関数を使用しているため削除されませんが、data1 イベントは正常に実行されます。縛られていない。ここで注意すべき点は、エミットがイベントをトリガーした後、そのイベントにバインドされているすべてのコールバック関数が呼び出されるということです。コールバック関数でremoveListener関数を使用して別のコールバックを削除しても、その後のイベント キューは役に立ちません。コールバックを削除しました。以下に示すように:

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;);

6. イベント リスナーとリスニング関数の数を取得します

指定されたイベントのリスナーの数を取得するには、emiter.listeners(eventName) 関数を使用します。指定されたイベントのすべてのリスナーを取得するために使用されます。 listen 関数は次のように使用されます:

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()解除所有事件的绑定。


実行結果は次のとおりです:


E:developmentdocumentnodejsdemo>nodeevent-example.js

データイベントエミッタ インスタンスのは 2 つのコールバック関数にバインドされています

それらは次のとおりです: [ [関数: cbA]、[関数: cbB] ]

7. エミッタ リスナーの最大数を取得および設定します

nodejs は、同じイベントは 10 を超えてはなりません。これは、次のように EventEmitter.defaultMaxListeners プロパティを確認することでわかります。

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;));


emitter は getMaxListeners() メソッドを通じてリスナーの最大数を取得し、最大数を設定します以下に示すように、setMaxListeners(n) メソッドを介してリスナーの数を変更します。

実行結果は次のとおりです:

E:developmentdocumentnodejsdemo>nodeevent-example.js
エミッターイベントリスナーの最大数は: 1
(node:6808) 警告: EventEmitter のメモリリークの可能性が 2 つのデータリスナー
で検出されました。制限を増やすには、エミッター .setMaxListeners() を使用します

上記の結果に示されているように、リスナーの最大数が設定されている場合は、同じイベントのリスナーの最大数を超えないようにすることが最善です。メモリリークの原因となります。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。