JS原生实现EventEmitter事件队列

2023-03-01  本文已影响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. 从零带你手写一个“发布-订阅者模式“ ,保姆级教学
上一篇下一篇

猜你喜欢

热点阅读