Node.js EventEmitter


Semua operasi I/O tak segerak dalam Node.js akan menghantar acara ke baris gilir acara apabila selesai.

Banyak objek dalam Node.js akan memancarkan peristiwa: objek net.Server akan memancarkan peristiwa setiap kali terdapat sambungan baharu dan objek fs.readStream akan memancarkan peristiwa apabila fail dibuka. Semua objek penjanaan peristiwa ini ialah kejadian peristiwa.EventEmitter.


Kelas EventEmitter

Modul peristiwa hanya menyediakan satu objek: peristiwa.EventEmitter. Teras EventEmitter ialah enkapsulasi pencetus peristiwa dan fungsi pendengar peristiwa.

Anda boleh mengakses modul ini melalui require("events");.

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

Objek EventEmitter akan mencetuskan acara 'ralat' jika ralat berlaku semasa instantiasi. Peristiwa 'newListener' dicetuskan apabila pendengar baharu ditambahkan dan acara 'removeListener' dicetuskan apabila pendengar dialih keluar.

Di bawah ini kami menggunakan contoh mudah untuk menggambarkan penggunaan 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);

Hasil pelaksanaan adalah seperti berikut:

Jalankan kod ini, dan konsol mengeluarkan selepas 1 saat 'sesetengah peristiwa_peristiwa dicetuskan'. Prinsipnya ialah objek acara mendaftarkan pendengar untuk acara some_event, dan kemudian kami menggunakan setTimeout untuk menghantar acara some_event ke objek acara selepas 1000 milisaat Pada masa ini, pendengar untuk some_event akan dipanggil.

$ node event.js 
some_event 事件触发

Setiap acara EventEmitter terdiri daripada nama acara dan beberapa parameter Nama acara ialah rentetan, yang biasanya menyatakan semantik tertentu. Untuk setiap acara, EventEmitter menyokong beberapa pendengar acara.

Apabila peristiwa dicetuskan, pendengar acara yang didaftarkan pada acara ini dipanggil dalam urutan dan parameter acara dihantar sebagai parameter fungsi panggil balik.

Mari kita terangkan proses ini dengan contoh berikut:

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

Laksanakan kod di atas, dan keputusan yang dijalankan adalah seperti berikut:

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

Dalam contoh di atas, pemancar mendaftarkan dua acara untuk pendengar acara someEvent, dan kemudian acara someEvent dicetuskan.

Anda boleh melihat dalam hasil yang sedang berjalan bahawa dua fungsi panggil balik pendengar acara dipanggil berturut-turut. Ini adalah penggunaan EventEmitter yang paling mudah.

EventEmitter menyediakan berbilang sifat, seperti on dan emit. Fungsi on digunakan untuk mengikat fungsi acara dan atribut emit digunakan untuk mencetuskan acara. Seterusnya, mari kita lihat lebih dekat sifat EventEmitter.

Kaedah

序号方法 & 描述
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。

Kaedah kelas

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

Acara

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

  • listener - 处理事件函数

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

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

  • listener - 处理事件函数

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

Contoh

Contoh berikut menunjukkan penggunaan kelas EventEmitter melalui acara sambungan.

Buat fail main.js dengan kod berikut:

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("程序执行完毕。");

Hasil pelaksanaan kod di atas adalah seperti berikut:

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

acara ralat

EventEmitter Ralat acara khas ditakrifkan, yang mengandungi semantik ralat Apabila kita hadapi Peristiwa ralat biasanya dicetuskan apabila pengecualian berlaku.

Apabila ralat dicetuskan, EventEmitter menetapkan bahawa jika tiada tindak balas Jika pendengar yang sepadan digunakan, Node.js akan menganggapnya sebagai pengecualian, keluar dari program dan mengeluarkan mesej ralat.

Kami biasanya perlu menyediakan ralat untuk mencetuskan Tetapkan pendengar pada objek acara untuk mengelakkan keseluruhan program ranap apabila ralat ditemui. Contohnya:

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

Ralat berikut akan dipaparkan semasa menjalankan:

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)

Mewarisi EventEmitter

Selalunya kami tidak akan menggunakan EventEmitter secara langsung, tetapi mewarisi ia dalam objek itu. Termasuk fs, net, Termasuk http, selagi modul teras yang menyokong tindak balas acara adalah subkelas EventEmitter.

Mengapa anda melakukan ini? Terdapat dua sebab:

Pertama, pelaksanaan acara objek dengan fungsi entiti tertentu mematuhi semantik, Mendengar dan memancarkan peristiwa haruslah kaedah sesuatu objek.

Kedua, mekanisme objek JavaScript adalah berdasarkan prototaip dan sokongan Warisan berbilang separa, mewarisi EventEmitter tidak akan mengganggu hubungan warisan asal objek.