美文网首页
JS原生实现EventEmitter事件队列

JS原生实现EventEmitter事件队列

作者: 斐硕人 | 来源:发表于2023-03-01 19:51 被阅读0次

    EventEmitter 是什么

    • Node.js 的 events 模块对外提供了一个 EventEmitter 对象,用于对 Node.js 中的事件进行统一管理。
    • Node.js 采用了事件驱动机制, EventEmitter 就是 Node.js 实现事件驱动的基础,Node.js 中几乎所有的模块都继承了这个类,以实现异步事件驱动架构。
    • Node.js 中几乎所有的模块都继承了这个类,以实现异步事件驱动架构。浏览器事件(如鼠标单击click,键盘事件keyDown)等都是该模式的例子

    核心代码-参考1

    使用 events 模块,对事件数组进行管理,
    on 添加进事件队列 addListener
    emit 执行
    off 关闭 removeListener
    once 只执行一次,结束后 remove

    class EventEmitter {
        constructor(){
            this.events = {}
        }
    
        on(event, listener){
            let listeners = this.events[event] || []
            listeners.push(listener)
            this.events = listeners
    
            return this
        }
    
        emit(event, ...args){
            let listeners = this.events[event]
    
            listeners.forEach(listener => {
                listener(...args)
            });
    
            return this
        }
    
        off(event, listener){
            let listeners = this.events[event]
    
            this.events[event] = listeners && listeners.filter(fn => fn !== listener) 
    
            return this
        }
    
        once(event, listener){
            let fn = function(...args){
                listener(...args)
    
                this.off(event, listener)
            }
    
            this.on(event, fn)
    
            return this
        }
    }
    

    优化-参考2

    添加事件合法性校验等

    function EventEmitter() {
      this.__events = {};
    }
    EventEmitter.VERSION = "1.0.0";
    
    EventEmitter.prototype.on = function (eventName, listener) {
      // 验证参数
      if (!eventName && !listener) {
        return;
      }
      // 回调的litener是否是函数
      if (!isValidKistener(listener)) {
        throw new TypeError("listener must be a function");
      }
      const events = this.__evnets;
      const listeners = (events[eventName] = evnets[eventName] || []);
      const listenerIsWrapped = typeof listener === "object";
      // 不重复添加事件,判断是否有相同
      if (indexOf(listeners.listener) === -1) {
        listeners.push(
          listenerIsWrapped
            ? listener
            : {
                listener: listener,
                once: false,
              }
        );
      }
      return this;
    };
    
    //判断是否是合法的listener
    const isValidListener = (listener) => {
      if (typeof listener === "function") {
        return true;
      } else if (listener && typeof listener === "object") {
        return isValidListener(listener.listener);
      } else {
        return false;
      }
    };
    
    // 判断新增自定义事件是否存在
    const indexOf = (array, item) => {
      let result = -1;
      item = typeof item === "object" ? item.listener : item;
      for (let i = 0; i < array.length; i++) {
        if (array[i].listener === item) {
          result = i;
          break;
        }
      }
      return result;
    };
    

    设计模式

    采用了发布-订阅者模式

    发布-订阅模式其实是一种对象间一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都将得到状态改变的通知。

    • 订阅者(Subscriber)把自己想订阅的事件 注册(Subscribe)到调度中心(Event Channel);
    • 当发布者(Publisher)发布该事件(Publish Event)到调度中心,也就是该事件触发时,由 调度中心 统一调度(Fire Event)订阅者注册到调度中心的处理代码

    相关文章

    1. 一文让你了解各种原生JS的实现方式
    2. 怎样轻松实现一个 EventEmitter?
    3. 被写烂系列——实现EventEmitter
    4. 从零带你手写一个“发布-订阅者模式“ ,保姆级教学

    相关文章

      网友评论

          本文标题:JS原生实现EventEmitter事件队列

          本文链接:https://www.haomeiwen.com/subject/dixnkdtx.html