EventEmitter 理解
Opened this issue · 0 comments
pfan123 commented
EventEmitter 事件发射器是一种发布,订阅模式,是event 模块提供的一个对象,用来注册事件可触发事件。Node 中的异步操作都是基于EventEmitter 来实现的。
EventEmitter主要API
- emitter.on(event, listener) 注册一个事件
- emitter.once(event, listener) 注册一个一次性的事件,触发后就被抹掉
- emitter.removeListener(event, listener) 在时间队列中剔除某一个事件
- emitter.removeAllListeners([event]) 删除整个事件队列,或多个事件
- emitter.listeners(event) 返回某些事件 emitter.emit(event, [arg1], [arg2], […]) 触发事件,可传入具体参数
EventEmitter使用方式
- 实例化获取EventEmitter
const events = require('events');
const emitter = new events.EventEmitter();
// 绑定sayHi事件,可以绑定多个同名事件,触发时会顺序触发
emitter.on('sayHi', function(someone){
console.log("我是", someone)
})
emitter.on('sayHi', function(someone){
console.log("我就是", someone)
})
// 触发sayHi事件
emitter.emit('sayHi', 'pfan');
// 我是pfan
// 我就是pfan
继承获取事件对象的方法
const util = require('util');
const events = require('events');
// 创建自定义对象
let Cat = function (name) {
this.name = name;
}
// 继承events.EventEmitter
util.inherits(Cat, events.EventEmitter);
// 创建自定义对象实例
let Tom = new Cat('Tom');
// 绑定sayHiTo事件
Tom.on('sayHi', function(someone){
// this指向实例Tom
console.log(this.name," sayHiTo ", someone)
})
Tom.emit('sayHiTo', 'pfan')
// 输出
// Tom sayHiTo pfan
Node.js中大部分的模块,都继承自Event模块,来异步操作处理如request、stream
常见Event Emitter工具库实现
可以采用现有的成熟框架,通过继承即可食用:
Component: component/emitter
Bower or standalone: Wolfy87/EventEmitter
EventEmitter的实现原理
EventEmitter实现并不难,可以实现一个简单的版本,加深理解。具备以下基本功能:
- on: 为特定事件添加监听器
- off: 为特定事件移除监听器
- emit: 触发特定事件
- once: 注册只执行一次的监听器
function Emitter(){
this.events = {}
}
Emitter.prototype.on = function(type, listener){
// 在事件对象中加入新的属性
// 确保新的属性以数组的形式保存
this.events[type] = this.events[type] || [];
// 在数组中加入事件处理函数
this.events[type].push(listener);
}
Emitter.prototype.off = function(type, listener){
if(this.events && this.events[type]){
delete this.events[type]
listener(...arguments)
}
}
Emitter.prototype.once = function(type, listener){
let self = this
this.on(type, function(){
self.off(type)
listener(...arguments)
})
}
Emitter.prototype.emit = function(type, arg){
if(this.events[type]) {// 如果事件对象中含有该属性
this.events[type].forEach(function(listener){
listener(arg)
})
}
}
module.exports = Emitter;
component/emitter 源码分析
/**
* 使用 `Emitter` 方式
*/
var Emitter = require('emitter');
var emitter = new Emitter;
emitter.emit('something');
on(event, listener)
为指定事件注册一个监听器,接受一个字符串 event 和一个回调函数。
emit(event, [arg1], [arg2], [...])
按参数的顺序执行每个监听器,如果事件有注册监听返回 true,否则返回 false。
/**
* 使用 `Emitter` 方式
*/
/**
* 设置导出 `Emitter` 类
*/
if (typeof module !== 'undefined') {
module.exports = Emitter;
}
/**
* Initialize a new `Emitter`.
*
* @api public
*/
function Emitter(obj) {
if (obj) return mixin(obj);
};
/**
* Mixin the emitter properties.
* 浅拷贝 Emitter.prototype
* @param {Object} obj
* @return {Object}
* @api private
*/
function mixin(obj) {
for (var key in Emitter.prototype) {
obj[key] = Emitter.prototype[key];
}
return obj;
}
/**
* Listen on the given `event` with `fn`.
* 事件只执行一次
* @param {String} event
* @param {Function} fn
* @return {Emitter}
* @api public
*/
Emitter.prototype.on =
Emitter.prototype.addEventListener = function(event, fn){
this._callbacks = this._callbacks || {};
(this._callbacks['$' + event] = this._callbacks['$' + event] || [])
.push(fn);
return this;
};
/**
* Adds an `event` listener that will be invoked a single
* time then automatically removed.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
* @api public
*/
Emitter.prototype.once = function(event, fn){
function on() {
this.off(event, on);
fn.apply(this, arguments);
}
on.fn = fn;
this.on(event, on);
return this;
};
/**
* Remove the given callback for `event` or all
* registered callbacks.
* 移除注册的监听器
* @param {String} event
* @param {Function} fn
* @return {Emitter}
* @api public
*/
Emitter.prototype.off =
Emitter.prototype.removeListener =
Emitter.prototype.removeAllListeners =
Emitter.prototype.removeEventListener = function(event, fn){
this._callbacks = this._callbacks || {};
// all
if (0 == arguments.length) {
this._callbacks = {};
return this;
}
// specific event
var callbacks = this._callbacks['$' + event];
if (!callbacks) return this;
// remove all handlers
if (1 == arguments.length) {
delete this._callbacks['$' + event];
return this;
}
// remove specific handler
var cb;
for (var i = 0; i < callbacks.length; i++) {
cb = callbacks[i];
if (cb === fn || cb.fn === fn) {
callbacks.splice(i, 1);
break;
}
}
return this;
};
/**
* Emit `event` with the given args.
* 事件发射告诉监听器开始执行
* @param {String} event
* @param {Mixed} ...
* @return {Emitter}
*/
Emitter.prototype.emit = function(event){
this._callbacks = this._callbacks || {};
var args = [].slice.call(arguments, 1)
, callbacks = this._callbacks['$' + event];
if (callbacks) {
callbacks = callbacks.slice(0);
for (var i = 0, len = callbacks.length; i < len; ++i) {
callbacks[i].apply(this, args);
}
}
return this;
};
/**
* Return array of callbacks for `event`.
* 返回监听
* @param {String} event
* @return {Array}
* @api public
*/
Emitter.prototype.listeners = function(event){
this._callbacks = this._callbacks || {};
return this._callbacks['$' + event] || [];
};
/**
* Check if this emitter has `event` handlers.
* 检测是否含有监听器
* @param {String} event
* @return {Boolean}
* @api public
*/
Emitter.prototype.hasListeners = function(event){
return !! this.listeners(event).length;
};
Component: component/emitter
Bower or standalone: Wolfy87/EventEmitter
Node.js EventEmitter
理解Event Emitter
深入浅出Node.js(四):Node.js的事件机制