手写实现EventEmitter

1.EventEmittet简单介绍

events模块是nodejs服务端知识,但是大多数Node.js核心都是基于异步的思想进行开发的events模块也不例外。

  • Node.js的events模块对外提供了EventEmitter对象,用于对Node.js中的事件进行统一管理
  • 在EventEmitter的基础上,几乎所有的模块都继承了这个类,以实现异步事件驱动框架。

2.EventEmitter基本用法

var events = require('events');
var eventBus = new  events.EventEmitter();
eventBus.on('say',function(message, name){
    console.log(message, name);
})

eventBus.emit('say','Hello','Join')

EventEmitter常用的API:

3. 手写实现浏览器端的EventEmitter

EventEmitter采用的是发布-订阅模式,发布-订阅模式其实是观察者模式的一种变形,区别在于:发布-订阅模式在观察者模式基础上增加了一个调度中心。

// 初始化代码
function EventEmitter(){
    this.__events={}
}
EventEmitter.VERSION='1.0.0'
// 实现on方法
EventEmitter.prototype.on = function(eventName, listener){
    if(!eventName || !listener) return;
    // 判断listener是否为函数
    if(!isValidListener(listener)){
        throw new TypeError('listener must be a function');
    }

    var events = this.__events;
    var listeners = events[eventName] = events[eventName]||[];
    var listenerWrapped = typeof listener === "object";
    // 不重复添加事件,判断是否有一样的
    if(indexOf(listeners, listener)===-1){
        listeners.push(listenerWrapped?listener:{
            listener:listener,
            once:false
        });
    }
    return this;
}

// 判断是否是合法的listener
function isValidListener(listener){
    if(typeof listener==='function'){
        return true
    }else if(listener&&typeof listener==='object'){
        return isValidListener(listener.listener);
    }else{
        return false
    }
}
// 判断新增自定义事件是否存在
function indexOf(array, item){
    var result = -1
    item = typeof item==='object'?item.listener:item;

    for(var i=0,len=array.length;i<len;i++){
        if(array[i].listener===item){
            result = i;
            break;
        }
    }
    return result
}

// 实现触发
EventEmitter.prototype.emit = function(eventName, args){
    // 直接通过内部对象获取对应自定义事件的回调函数
    var listener = this.__events[eventName];
    if(!listener) return;
    // 需要考虑多个listener的情况
    for(var i=0; i<listener.length; i++){
        var listener = listeners[i]
        if(listener){
            listener.listener.apply(this, args||[])
            // 给listener中once为true进行特殊处理
            if(listener.once){
                this.off(eventName, listener.listener)
            }
        }
    }
    return this
}

EventEmitter.prototype.off = function(eventName, listener){
    var listeners = this.__events[eventName];
    if(!listeners) return;

    var index;
    for(var i=0,len=listeners.length;i<len;i++){
        if(listeners[i]&&listeners[i].listener===listener){
            index = i;
            break;
        }
    }
    // off关键字
    if(typeof index!=='undefined'){
        listeners.splice(index, i, null)
    }
    return this
}

EventEmitter.prototype.once = function(eventName, listener){
    // 直接调用on方法, once传入参数true, 待执行之后进行once处理
    return this.on(eventName,{
        listener:listener,
        once:true
    })
}

EventEmitter.prototype.allOff = function (eventName) {
    // 如果eventName存在,直接清空listeners的数组
    if(eventName&&this.__events[eventName]){
        this.__events[eventName] = []
    }else{
        this.__events={}
    }
  }




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值