node 根据事件驱动,那基本都是回调,最常用的叫发布订阅模式,什么叫发布订阅呢?对比观察者模式,前者是主动地,后者是被动的
//发布订阅模式
//将时间放到数组中,当真的发生时在执行
//let EventEmitter = require('events');
let EventEmitter = require('./EventEmitter');
let {inherits} = require('util');
function Girl(){}
inherits(Girl,EventEmitter);
let girl = new Girl;
let cry = () =>{
console.log('cry')
}
let drink = () =>{
console.log('drink')
}
girl.on('one',cry)
girl.on('two',drink)
girl.emit('two')
复制代码
可以正常输出1.txt里面的内容,那么EventEmitter是如何实现的呢?
EventEmitter实现
EventEmitter骨架
function EventEmitter(){
}
EventEmitter.prototype.on = function(type,callback){
}
EventEmitter.prototype.emit = function(type){
}
module.exports = EventEmitter;
复制代码
EventEmitter.on
function EventEmitter(){
this._events = {};
}
//this._events = {one:[cry],two:[drink]}
EventEmitter.prototype.on = function(type,callback){
//如果实例不存在则会创建一个空对象
if(!this._events) this._events = Object.create(null) //继承会找不到event ,直接实例可以, Cannot read property 'one' of undefined 初始化this._events
// this._events ={} 和 this._events = Object.create(null) 的区别 前者原型指针指向object链,后者没有任何属性,后者可以避免第三方继承
if(this._events[type]){ // 查看事件名称是否存在
this._events[type].push(callback)
}else{
this._events[type] = [callback] //将事件绑定在对象上
}
}
复制代码
**EventEmitter.newListener || EventEmitter.addListener **
EventEmitter.addListener = EventEmitter.prototype.on = function(type,callback){
//如果实例不存在则会创建一个空对象
if(!this._events) this._events = Object.create(null)
if(this.newListener && this._events['newListener'] && this._events['newListener'].length>0){
if(type != 'newListener'){
this._events['newListener'].forEach(fn => fn(type))
}
}//继承会找不到event ,直接实例可以, Cannot read property 'one' of undefined 初始化this._events
// this._events ={} 和 this._events = Object.create(null) 的区别 前者原型指针指向object链,后者没有任何属性,后者可以避免第三方继承
if(this._events[type]){ // 查看事件名称是否存在
this._events[type].push(callback)
}else{
this._events[type] = [callback] //将事件绑定在对象上
}
}
复制代码
EventEmitter.defaultMaxListeners || emitter.getMaxListeners() || emitter.setMaxListeners()
EventEmitter.defaultMaxListeners = 10; //默认最大监听数
EventEmitter.prototype.setMaxListeners = function(count){
this._count = count;
}
EventEmitter.prototype.getMaxListeners = function(){
return this._count || EventEmitter.defaultMaxListeners
}
EventEmitter.addListener = EventEmitter.prototype.on = function(type,callback){
...
if(this._events[type].length === this.getMaxListeners()){
console.warn('memeoy link detected')
}
}
复制代码
EventEmitter.eventNames || listeners
EventEmitter.prototype.eventNames = function(){
return Object.keys(this._events)
}
EventEmitter.prototype.listeners = function(type){
return this._events[type]
}
复制代码
removeListener || removeAllListeners
//找到数组里的方法对应的移除掉即可
EventEmitter.prototype.removeListener = function(type,callback){
if (typeof callback !== 'function') throw new TypeError('"callback" argument must be a function');
if(this._events[type]){
// filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。
//this._events[type] = this._events[type].filter(fn => fn != callback)
//一次只删除一个,不是删除所有相同的type,应该用下面方法
// for(let i = 0;i < this._events[type].length;i++){
// if(this._events[type][i] == callback){
// this._events[type].splice[i]
// break;
// }
// }
//同上效果
this._events[type].splice(this._events[type].indexOf(callback),1)
}
}
EventEmitter.prototype.removeAllListeners = function(type){
if(this._events[type]){
return this._events[type] = Obj.create(null)
}else{
}
}
复制代码
EventEmitter.once
EventEmitter.prototype.once = function (type,callback){
//当emit时warp执行需要继续将参数传递给callback
let warp = (...args) =>{
callback(...args);
this.removeListener(type,warp) //用on绑定的时候,在emit的时候执行wap
}
warp.l = callback;//将callback方法挂在到warp属性上
this.on(type,warp);
}
//在once包了一层wap,我们需要对此wap做细节处理
复制代码
emit
EventEmitter.prototype.emit = function(type , ...args){
if(this._events[type]){
this._events[type].forEach(fn => fn(...args));
}else{
this._events = {}
}
}
//找到数组里的方法对应的移除掉即可
EventEmitter.prototype.removeListener = function(type,callback){
if (typeof callback !== 'function') throw new TypeError('"callback" argument must be a function');
if(this._events[type]){
// filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。
//this._events[type] = this._events[type].filter(fn =>{
// return fn != callback && fn.l != callback
// })
//一次只删除一个,不是删除所有相同的type,应该用下面方法
for(let i = 0;i < this._events[type].length;i++){
if(this._events[type][i] == callback || this._events[type][i].l == callback ){
this._events[type].splice[i]
break;
}
}
//不考虑warp同上效果
//this._events[type].splice(this._events[type].indexOf(callback) ,1)
}
}
复制代码
所以现在我们写出的代码总结如下
function EventEmitter(){
this._events = {}
}
//this._events = {one:[cry],two:[drink]}
EventEmitter.prototype.eventNames = function(){
return Object.keys(this._events)
}
EventEmitter.prototype.listeners = function(type){
return this._events[type]
}
EventEmitter.defaultMaxListeners = 10; //默认最大监听数
EventEmitter.prototype.setMaxListeners = function(count){
this._count = count;
}
EventEmitter.prototype.getMaxListeners = function(){
return this._count || EventEmitter.defaultMaxListeners
}
EventEmitter.addListener = EventEmitter.prototype.on = function(type,callback){
//如果实例不存在则会创建一个空对象
if(!this._events) this._events = Object.create(null) //继承会找不到event ,直接实例可以, Cannot read property 'one' of undefined 初始化this._events
// this._events ={} 和 this._events = Object.create(null) 的区别 前者原型指针指向object链,后者没有任何属性,后者可以避免第三方继承
//如果当前不是newListenernewListener方法就需要让newListener回调一次执行,传入类
if(this.newListener && this._events['newListener'] && this._events['newListener'].length>0){
if(type != 'newListener'){
this._events['newListener'].forEach(fn => fn(type))
}
}
if(this._events[type]){ // 查看事件名称是否存在
this._events[type].push(callback)
}else{
this._events[type] = [callback] //将事件绑定在对象上
}
if(this._events[type].length === this.getMaxListeners()){
console.warn('memeoy link detected')
}
}
EventEmitter.prototype.emit = function(type , ...args){
if(this._events[type]){
this._events[type].forEach(fn => fn(...args));
}else{
this._events = {}
}
}
//找到数组里的方法对应的移除掉即可
EventEmitter.prototype.removeListener = function(type,callback){
if (typeof callback !== 'function') throw new TypeError('"callback" argument must be a function');
if(this._events[type]){
// filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。
//this._events[type] = this._events[type].filter(fn =>{
// fn != callback && fn.l != callback
// })
//一次只删除一个,不是删除所有相同的type,应该用下面方法
for(let i = 0;i < this._events[type].length;i++){
if(this._events[type][i] == callback || this._events[type][i].l == callback ){
this._events[type].splice[i]
break;
}
}
//不考虑warp同上效果
//this._events[type].splice(this._events[type].indexOf(callback) ,1)
}
}
EventEmitter.prototype.removeAllListeners = function(type){
if(this._events[type]){
return this._events[type] = Obj.create(null)
}else{
}
}
EventEmitter.prototype.once = function (type,callback){
//当emit时warp执行需要继续将参数传递给callback
let warp = (...args) =>{
callback(...args);
this.removeListener(type,warp) //用on绑定的时候,在emit的时候执行wap
}
warp.l = callback;//将callback方法挂在到warp属性上
this.on(type,warp);
}
module.exports = EventEmitter;
复制代码
测试代码
//发布订阅模式
//将时间放到数组中,当真的发生时在执行
// let EventEmitter = require('events');
let EventEmitter = require('./EventEmitter');
let {inherits} = require('util');
function Girl(){
}
inherits(Girl,EventEmitter);
let girl = new Girl;
let cry = (a,b,c) =>{
console.log('cry',a,b,c)
}
let drink = () =>{
console.log('drink')
}
girl.on('newListener',(type) => {
console.log(type)
})
girl.on('one',cry)
girl.on('one',drink)
girl.on('one',cry)
girl.removeListener('one',cry) //找到one把 事件删掉
girl.emit('one',1,2,3);
console.log(girl.eventNames())
console.log(girl.listeners('one'))
复制代码
util使用
我们经常用的util模块(node 8版本以上)
let {promisify,inherits} = require('util');
let fs = require('fs');
let read = promisify(fs.readFile); //
read('1.txt','utf8').then(data =>{
console.log(data)
})
//相当于
async function r(){
try{
let result = await read('1.txt','utf8')
return result;
}catch(e){
throw e;
}
}
r().then(data=>{
console.log(data)
},err=>{console.log(err)})
//koa 后期也是采用 async await
function A(){
}
A.prototype.a = 1;
function B(){
}
inherits(B,A)//b继承a 之继承公有方法
let b = new B()
console.log(b.a);
//相当于
B.prototype = Object.create(A.prototype)
//相当于
B.prototype.__proto__ = A.prototype
//相当于
Object.setPrototypeOf(B.prototype,A.prototype)
原文作者:dlzhao
本文来源: 掘金 如需转载请联系原作者