Node.js のすべての非同期 I/O 操作は、完了時にイベントをイベント キューに送信します。
Node.js の多くのオブジェクトはイベントを発行します。net.Server オブジェクトは新しい接続が確立されるたびにイベントを発行し、fs.readStream オブジェクトはファイルが開かれるときにイベントを発行します。これらのイベント生成オブジェクトはすべて events.EventEmitter のインスタンスです。
イベントエミッタークラス
events モジュールは、events.EventEmitter という 1 つのオブジェクトのみを提供します。EventEmitter の中核は、イベント トリガー関数とイベント リスナー関数のカプセル化です。
このモジュールには、require("events"); 経由でアクセスできます。
// 引入 events 模块
var events = require('events');
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();
EventEmitter オブジェクトは、インスタンス化中にエラーが発生した場合にエラー イベントを発生します。newListener イベントは、新しいリスナーが追加されるときに発生し、removeListener イベントは、リスナーが削除されるときに発生します。
簡単な例を使用して、EventEmitter の使用法を説明してみましょう。
//event.js 文件
var EventEmitter = require('events').EventEmitter;
var event = new EventEmitter();
event.on('some_event', function() {
console.log('some_event 事件触发');
});
setTimeout(function() {
event.emit('some_event');
}, 1000);
実行結果は以下の通りです。
このコードを実行すると、1 秒後にコンソールに 「some_event イベントがトリガーされました」と出力されます。原則として、イベント オブジェクトがイベント some_event のリスナーを登録し、1000 ミリ秒後に setTimeout を通じてイベント オブジェクトにイベント some_event を送信します。この時点で some_event のリスナーが呼び出されます。
$ node event.js
some_event 事件触发
EventEmitter の各イベントは、イベント名といくつかのパラメーターで構成されており、イベント名は通常、特定のセマンティクスを表す文字列です。イベントごとに、EventEmitter は複数のイベント リスナーをサポートします。
イベントがトリガーされると、このイベントに登録されているイベント リスナーが順番に呼び出され、イベント パラメータがコールバック関数のパラメータとして渡されます。
次の例を使用してこのプロセスを説明しましょう。
//event.js 文件
var events = require('events');
var emitter = new events.EventEmitter();
emitter.on('someEvent', function(arg1, arg2) {
console.log('listener1', arg1, arg2);
});
emitter.on('someEvent', function(arg1, arg2) {
console.log('listener2', arg1, arg2);
});
emitter.emit('someEvent', 'arg1 参数', 'arg2 参数');
上記のコードを実行すると、操作の結果は次のようになります。
$ node event.js
listener1 arg1 参数 arg2 参数
listener2 arg1 参数 arg2 参数
上の例では、エミッターはイベント someEvent に対して 2 つのイベント リスナーを登録し、someEvent イベントをトリガーします。
実行結果では、2 つのイベント リスナー コールバック関数が連続して呼び出されていることがわかります。これは EventEmitter の最も単純な使用法です。
EventEmitter は、 on や Emitなどの複数のプロパティを提供します 。on 関数はイベント関数をバインドするために使用され、emit プロパティはイベントをトリガーするために使用されます。次に、EventEmitter のプロパティを詳しく見てみましょう。
方法
シリアルナンバー | 方法と説明 | |
1 | addListener(event,listener) は、 指定されたイベントのリスナー配列の末尾にリスナーを追加します。 |
|
2 | on(event,listener) は、 |
|
3 |
|
|
4 | RemoveListener(イベント、リスナー) 指定されたイベントのリスナーを削除します。リスナーはイベントに登録されたリスナーである必要があります。 2 つのパラメータを受け入れます。1 つ目はイベント名、2 つ目はコールバック関数名です。 |
|
5 | RemoveAllListeners([event]) は、 すべてのイベントのすべてのリスナーを削除します。イベントが指定されている場合は、指定されたイベントのすべてのリスナーを削除します。 |
|
6 |
|
|
7 | listeners(event) は、 指定されたイベントのリスナーの配列を返します。 |
|
8 | Emit(event, [arg1], [arg2], [...]) 各リスナーをリスナーの順序で実行し、イベントにリスナーが登録されている場合は true を返し、登録されていない場合は false を返します。 |
クラスメソッド
シリアルナンバー | 方法と説明 |
1 | listenerCount(emitter,event) は、 指定されたイベントのリスナーの数を返します。 |
events.EventEmitter.listenerCount(emitter, eventName) //已废弃,不推荐
events.emitter.listenerCount(eventName) //推荐
イベント
シリアルナンバー | イベントと説明 | |
1 |
|
|
2 |
|
例
次の例は、接続 (接続) イベントを介した EventEmitter クラスのアプリケーションを示しています。
次のコードを使用して main.js ファイルを作成します。
var events = require('events');
var eventEmitter = new events.EventEmitter();
// 监听器 #1
var listener1 = function listener1() {
console.log('监听器 listener1 执行。');
}
// 监听器 #2
var listener2 = function listener2() {
console.log('监听器 listener2 执行。');
}
// 绑定 connection 事件,处理函数为 listener1
eventEmitter.addListener('connection', listener1);
// 绑定 connection 事件,处理函数为 listener2
eventEmitter.on('connection', listener2);
var eventListeners = eventEmitter.listenerCount('connection');
console.log(eventListeners + " 个监听器监听连接事件。");
// 处理 connection 事件
eventEmitter.emit('connection');
// 移除监绑定的 listener1 函数
eventEmitter.removeListener('connection', listener1);
console.log("listener1 不再受监听。");
// 触发连接事件
eventEmitter.emit('connection');
eventListeners = eventEmitter.listenerCount('connection');
console.log(eventListeners + " 个监听器监听连接事件。");
console.log("程序执行完毕。");
上記のコードの実行結果は次のようになります。
$ node main.js
2 个监听器监听连接事件。
监听器 listener1 执行。
监听器 listener2 执行。
listener1 不再受监听。
监听器 listener2 执行。
1 个监听器监听连接事件。
程序执行完毕。
エラーイベント
EventEmitter は、間違ったセマンティクスを含む特別なイベント エラーを定義しており、通常、例外が発生したときにエラー イベントをトリガーします。
エラーがトリガーされた場合、EventEmitter は、応答するリスナーがない場合に Node.js がそれを例外として扱い、プログラムを終了してエラー メッセージを出力することを指定します。
通常、エラー発生後にプログラム全体がクラッシュするのを避けるために、エラー イベントをトリガーするオブジェクトのリスナーを設定する必要があります。例えば:
var events = require('events');
var emitter = new events.EventEmitter();
emitter.emit('error');
実行すると次のエラーが表示されます。
node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: Uncaught, unspecified 'error' event.
at EventEmitter.emit (events.js:50:15)
at Object.<anonymous> (/home/byvoid/error.js:5:9)
at Module._compile (module.js:441:26)
at Object..js (module.js:459:10)
at Module.load (module.js:348:31)
at Function._load (module.js:308:12)
at Array.0 (module.js:479:10)
at EventEmitter._tickCallback (node.js:192:40)
イベントエミッタの継承
ほとんどの場合、EventEmitter を直接使用することはなく、オブジェクト内で継承します。イベント応答をサポートするコア モジュールが EventEmitter のサブクラスである限り、fs、net、http が含まれます。
なぜこれをしたいのですか?理由は 2 つあります。
まず、あるエンティティ機能を持つオブジェクトによるイベントの実装はセマンティクスに準拠しており、イベントの監視と発生はオブジェクトのメソッドである必要があります。次に、JavaScript のオブジェクト機構はプロトタイプに基づいており、部分的な多重継承をサポートしているため、EventEmitter を継承しても、オブジェクト本来の継承関係が崩れることはありません。