Events 事件模块
说明
大多数 Node.js 核心 API 都采用异步事件驱动架构,其中某些类型的对象(触发器)会周期性的触发命名事件来调用函数对象(监听器),所有能触发事件的对象都是
EventEmitter
类的实例,允许将一个或者多个函数绑定到会被对象触发的命名事件上
EventEmitter
会按照监听器函数的注册顺序同步的调用所有监听器,所以需要确保事件的正确排序且避免竞争条件或逻辑错误,监听器函数中可以使用setImmediate()
或者process.nextTick()
方法切换到异步操作模式
参考
// 获取事件发生器的构造函数
const Emitter = require('events').EventEmitter;
// 创建事件发生器实例,也就是消息中心,用来注册和触发事件(订阅和发布)
const emitter = new Emitter();
// 事件响应函数
function handle1(some) {
console.log('handle - ', some);
}
function handle2(some) {
console.log('同步的', some);
process.nextTick(function () {
console.log('nextTick', some);
})
setImmediate(() => {
console.log('setImmediate', some);
})
}
// on 注册事件,指定回调函数
emitter.on('test', handle1);
emitter.on('test', handle2)
// emit 触发事件
setTimeout(function () {
console.log('start emit');
emitter.emit('test', 'test data');
console.log('end emit');
}, 1000);
/*
start emit
handle - test data
同步的 test data
end emit
nextTick test data
setImmediate test data
*/
Event Emitter 接口可以部署在任意对象上,使得这些对象也能够订阅和发布消息
// 获取事件发生器的构造函数
const Emitter = require('events').EventEmitter;
// 创建构造函数
function Test() {
this.name = 'test';
}
/*
使构造函数的原型继承事件发生器的原型方法
Object.create(a) 以 a 为原型创建对象
将事件发生器添加到构造函数原型对象的原型上,可以方便构造函数原型上继续添加方法(注意不要将原型对象覆盖)
*/
// Test.prototype.__proto__ = Emitter.prototype;
Test.prototype = Object.create(Emitter.prototype);
Test.prototype.say = function () {
console.log(this.name);
}
// 创建实例
const test = new Test();
// 事件响应函数
function handle(some) {
console.log('handle - ', some);
}
// 注册事件
test.on('test', handle);
// 触发事件
setTimeout(function () {
console.log('start emit');
test.emit('test', 'test extend');
console.log('end emit');
}, 1000);
Node.js 内置工具 util 模块提供 inherits 方法,用于继承
const Emitter = require('events').EventEmitter;
const util = require('util');
function Test() {
this.name = 'test name';
this.on('newListener', function (listener) {
console.log('listener: ', listener);
})
}
Test.prototype.init = function () {
this.emit('open', 'init open');
setTimeout(() => {
this.emit('close', 'init close');
}, 1000)
}
util.inherits(Test, Emitter); // Emitter 的接口继承到 Test 上
const test = new Test();
function handle(text) {
console.log(text);
}
test.on('open', handle);
test.on('close', handle);
test.init();
Event Emitter 实例方法
on()
给事件添加监听器函数,添加多个事件监听器会按照添加顺序依次执行once()
给事件添加监听器函数,只执行一次addListener()
与 on 一样emit()
按照监听器的注册顺序同步地调用每个注册在此事件下的监听器,并提供参数listeners()
返回名某个事件下的监听器数组removeListener()
两个参数:eventName, listener ,移除某个事件下的指定监听器removeAllListeners()
移除某个事件下的所有监听函数setMaxListeners()
修改指定实例的事件监听器上限getMaxListeners()
返回监听器限制值prependListener()
添加事件监听器到指定事件的开头prependOnceListener()
添加事件监听器到指定事件的开头,只执行一次listenerCount()
返回某个事件的监听器数量eventNames()
返回已注册的事件名的数组
const Emitter = require('events').EventEmitter;
const emitter = new Emitter();
function handle (f) {
return function (text) {
console.log(f, text);
}
}
// once 指定事件的监听函数只执行一次
emitter.once('onceEvent', handle('once'));
// on 指定事件的监听函数
emitter.on('onceEvent', handle('on'));
// addListener 与 on 一样
emitter.addListener('onceEvent', handle('addListener'));
// listeners 返回同一个事件下回调函数的数组
const listeners = emitter.listeners('onceEvent');
console.log(listeners); // length 3
// emit 触发事件
emitter.emit('onceEvent', 'emit1');
/*
once emit1
on emit1
addListener emit1
*/
emitter.emit('onceEvent', 'emit2');
/*
// once 只执行一次,所以没有响应
on emit2
addListener emit2
*/
// removeAllListeners 移除某个事件的所有监听函数
emitter.removeAllListeners('onceEvent');
emitter.emit('onceEvent', 'emit3'); // 没响应
function handle2(text) {
console.log('handle2 ', text);
}
function handle3(text) {
console.log('handle3 ', text);
}
function handle4(text) {
console.log('handle4 ', text);
}
function handle5(text) {
console.log('handle5 ', text);
}
emitter.on('twiceEvent', handle2);
emitter.on('twiceEvent', handle3);
// prependListener 添加事件监听器到指定事件的开头
emitter.prependListener('twiceEvent', handle4); // 先执行
// prependOnceListener 添加事件监听器到指定事件的开头,只执行一次
emitter.prependOnceListener('twiceEvent', handle5);
// removeListener 移除某个事件的某个监听函数
emitter.removeListener('twiceEvent', handle2);
emitter.emit('twiceEvent', 'emit4'); // handle3 emit4; handle2 不响应
// setMaxListeners 修改指定实例的事件监听器上限
emitter.setMaxListeners(20);
// 返回监听器限制值
emitter.getMaxListeners(); // 20
// listenerCount 返回某个事件的监听器数量
emitter.listenerCount('twiceEvent') // 2
// eventNames 返回已注册的事件名的数组
emitter.eventNames() // [ 'twiceEvent' ]