夜深了,人静了,灵感来了,敲敲代码。
1、用法
// 非阻塞I/O
const EventEmitter=require('events'); //可以直接引用的模块,不需要自己写,或者引包,或者引入模块,就是核心模块
// 核心就是发布订阅 on 订阅 emit 发布 off 取消订阅 绑定一次 once
const events=new EventEmitter;
const cry=function(name){
console.log('哭',name);
}
events.on('女孩失恋了',cry);
events.on('女孩失恋了',function(name){
console.log('笑',name);
});
// 只执行,执行完毕后就将该函数移除,下次不会在继续触发了。
events.once('女孩失恋了',function(name){
console.log('逛街',name);
});
events.off('女孩失恋了',cry);
events.emit('女孩失恋了','boy');
events.emit('女孩失恋了','boy');
/* process.nextTick(()=>{
// nextTick 可以解决异步调用问题,方式优于promise.then();
events.emit('女孩失恋了','boy');
}) */
// 先订阅,再发布
// vue3 mitt
// 一般的继承:实例继承+原型继承+类属性继承 = es6 的extend
// 原型继承有3种方法
function Girl(){
}
/* Object.setPrototypeOf(Girl.prototype,EventEmitter.prototype); //es6
Girl.prototype=Object.create(EventEmitter); // es5
Girl.prototype._proto_=EventEmitter.prototype; // es */ // 多
// node.js 中提供的方法 原型继承
const util=require('util');
util.inherits(Girl,EventEmitter);
// splice 和filter 删除
2、实现原理
// node 内部实现的还是构造函数
function EventEmitter(){
this._events={};
}
EventEmitter.prototype.on=function(eventName,callback){
if(!this._events) this._events={};
const callbacks=this._events[eventName] ||[];
callbacks.push(callback);
this._events[eventName]=callbacks;
console.log(this._events);
}
EventEmitter.prototype.emit=function(eventName,...args){
if(!this._events) this._events={};
let callbacks=this._events[eventName];
if(callbacks){
callbacks.forEach(cb => {
cb(...args);
});
}
}
EventEmitter.prototype.off=function(eventName,callback){
if(!this._events) this._events={};
if(this._events[eventName]){
this._events[eventName]=this._events[eventName].filter(fn=>fn!=callback && fn.l !=callback)
}
}
EventEmitter.prototype.once=function(eventName,callback){
// 先绑定,执行完成后再删除
const one=(...args)=>{
callback(...args);
// 执行完毕后
// 删除事件
this.off(eventName,one);
}
// 先绑定事件
one.l=callback; // 自定义属性 创建关联
this.on(eventName,one);
}
module.exports=EventEmitter;
// 或 第一个为真,就不走后面了。
// on emit once off