Émetteur d'événements Node.js


Toutes les opérations d'E/S asynchrones dans Node.js envoient un événement à la file d'attente des événements une fois terminées.

De nombreux objets dans Node.js émettront des événements : un objet net.Server émettra un événement à chaque fois qu'il y aura une nouvelle connexion, et un objet fs.readStream émettra un événement à l'ouverture du fichier. Tous ces objets générateurs d'événements sont des instances de events.EventEmitter.


Classe EventEmitter

Le module events ne fournit qu'un seul objet : events.EventEmitter. Le cœur d'EventEmitter est l'encapsulation des fonctions de déclenchement d'événements et d'écoute d'événements.

Vous pouvez accéder à ce module via require("events");. L'objet

// 引入 events 模块
var events = require('events');
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();

EventEmitter déclenchera l'événement 'error' si une erreur se produit lors de l'instanciation. L'événement 'newListener' est déclenché lorsqu'un nouvel écouteur est ajouté, et l'événement 'removeListener' est déclenché lorsqu'un nouvel écouteur est supprimé.

Ci-dessous, nous utilisons un exemple simple pour illustrer l'utilisation de 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);

Les résultats de l'exécution sont les suivants :

Exécutez ce code et les sorties de la console après 1 seconde, « un événement some_event déclenché » . Le principe est que l'objet événement enregistre un écouteur pour l'événement some_event, puis nous utilisons setTimeout pour envoyer l'événement some_event à l'objet événement après 1000 millisecondes. À ce moment, l'écouteur de some_event sera appelé.

$ node event.js 
some_event 事件触发

Chaque événement de EventEmitter se compose d'un nom d'événement et de plusieurs paramètres. Le nom de l'événement est une chaîne, qui exprime généralement certaines sémantiques. Pour chaque événement, EventEmitter prend en charge plusieurs écouteurs d'événements.

Lorsqu'un événement est déclenché, les écouteurs d'événements enregistrés à cet événement sont appelés dans l'ordre et les paramètres de l'événement sont transmis en tant que paramètres de fonction de rappel.

Expliquons ce processus avec l'exemple suivant :

//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 参数');

Exécutez le code ci-dessus, et les résultats d'exécution sont les suivants :

$ node event.js 
listener1 arg1 参数 arg2 参数
listener2 arg1 参数 arg2 参数

Dans l'exemple ci-dessus, l'émetteur enregistre deux événements pour l'écouteur d'événement someEvent, puis l'événement someEvent est déclenché.

Vous pouvez voir dans les résultats en cours d'exécution que deux fonctions de rappel d'écouteur d'événements sont appelées successivement. Il s’agit de l’utilisation la plus simple d’EventEmitter.

EventEmitter fournit plusieurs propriétés, telles que on et emit. La fonction on est utilisée pour lier la fonction d'événement, et l'attribut emit est utilisé pour déclencher un événement. Examinons ensuite de plus près les propriétés de EventEmitter.

Méthode

序号方法 & 描述
1addListener(event, listener)
为指定事件添加一个监听器到监听器数组的尾部。
2on(event, listener)
为指定事件注册一个监听器,接受一个字符串 event 和一个回调函数。
server.on('connection', function (stream) {
  console.log('someone connected!');
});
3once(event, listener)
为指定事件注册一个单次监听器,即 监听器最多只会触发一次,触发后立刻解除该监听器。
server.once('connection', function (stream) {
  console.log('Ah, we have our first user!');
});
4removeListener(event, listener)
移除指定事件的某个监听器,监听器 必须是该事件已经注册过的监听器。
var callback = function(stream) {
  console.log('someone connected!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);
5removeAllListeners([event])
移除所有事件的所有监听器, 如果指定事件,则移除指定事件的所有监听器。
6setMaxListeners(n)
默认情况下, EventEmitters 如果你添加的监听器超过 10 个就会输出警告信息。 setMaxListeners 函数用于提高监听器的默认限制的数量。
7listeners(event)
返回指定事件的监听器数组。
8emit(event, [arg1], [arg2], [...])
按参数的顺序执行每个监听器,如果事件有注册监听返回 true,否则返回 false。

Méthode de classe

序号方法 & 描述
1listenerCount(emitter, event)
返回指定事件的监听器数量。

Événement

序号事件 & 描述
1newListener
  • event - 字符串,事件名称

  • listener - 处理事件函数

该事件在添加新监听器时被触发。

2removeListener
  • event - 字符串,事件名称

  • listener - 处理事件函数

从指定监听器数组中删除一个监听器。需要注意的是,此操作将会改变处于被删监听器之后的那些监听器的索引。

Exemples

Les exemples suivants démontrent l'application de la classe EventEmitter via l'événement de connexion.

Créez le fichier main.js avec le code suivant :

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 = require('events').EventEmitter.listenerCount(eventEmitter,'connection');
console.log(eventListeners + " 个监听器监听连接事件。");

// 处理 connection 事件 
eventEmitter.emit('connection');

// 移除监绑定的 listener1 函数
eventEmitter.removeListener('connection', listener1);
console.log("listener1 不再受监听。");

// 触发连接事件
eventEmitter.emit('connection');

eventListeners = require('events').EventEmitter.listenerCount(eventEmitter,'connection');
console.log(eventListeners + " 个监听器监听连接事件。");

console.log("程序执行完毕。");

Le résultat de l'exécution du code ci-dessus est le suivant :

$ node main.js
2 个监听器监听连接事件。
监听器 listener1 执行。
监听器 listener2 执行。
listener1 不再受监听。
监听器 listener2 执行。
1 个监听器监听连接事件。
程序执行完毕。

événement d'erreur

EventEmitter Une erreur d'événement spécial est définie, qui contient la sémantique de l'erreur lorsque nous la rencontrons. L'événement d'erreur est généralement déclenché lorsqu'une exception se produit.

Lorsqu'une erreur est déclenchée, EventEmitter stipule que s'il n'y a pas de réponse Si l'écouteur correspondant est utilisé, Node.js le traitera comme une exception, quittera le programme et affichera un message d'erreur.

On doit généralement préparer les erreurs au déclenchement Définissez un écouteur sur l'objet événement pour éviter que l'ensemble du programme ne plante lorsqu'une erreur est rencontrée. Par exemple :

var events = require('events'); 
var emitter = new events.EventEmitter(); 
emitter.emit('error');

L'erreur suivante s'affichera lors de l'exécution :

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)

Héritage d'EventEmitter

La plupart du temps, nous n'utiliserons pas directement EventEmitter, mais hériterons il dans l'objet il. Y compris fs, net, Y compris http, tant que les modules de base qui prennent en charge la réponse aux événements sont des sous-classes d'EventEmitter.

Pourquoi fais-tu ça ? Il y a deux raisons :

Premièrement, l'implémentation événementielle d'un objet avec une certaine fonction d'entité est conforme à la sémantique, L'écoute et l'émission d'événements doivent être des méthodes d'un objet.

Deuxièmement, le mécanisme objet de JavaScript est basé sur des prototypes et des supports Héritage multiple partiel, l'héritage d'EventEmitter ne perturbera pas la relation d'héritage d'origine de l'objet.