JavaScript handwriting series (2) - EventBus

foreword

Component parameter passing in Vue is a common requirement in daily development. Among them, EventBusthe event bus is one of the very useful ones. In fact, this kind of usage was relatively rejected before, because it was rarely used and did not understand it, so it was out of understanding of the unknown. Fear of things, more repelling. I recently read a handwritten EventBusarticle, and after reading it, I understood the general principle. Today, I will tell you about the basic implementation based on my own understanding.

We can EventBussimply understand it as an official account, in which the author of the official account has $emitthe ability to publish ( ) news, and the user has $onthe ability to subscribe ( ) to the official account. After the official account author publishes an article, the user will receive the content of the article. If you like to push articles, you can choose to unsubscribe ( $off) the ability of the official account. Next, let's simply implement these functions.

Code

function EventBus() {
  this.eventObj = {}; // 定义事件存储列表
  this.callbackId = 0; // 定义事件id  可以理解为公众号订阅者人数
}

// 订阅
EventBus.prototype.$on = function(key, callback) {
  if (this.eventObj[key] === undefined) {
    this.eventObj[key] = {}; // 如果不存在key的事件列表 则初始化为空  可以理解为 一个公众号可以有多个人订阅
  }
   const callbackIndex = this.callbackId++; // 先赋值再添加 每添加一个订阅者 人数加1
  this.eventObj[key][callbackIndex] = callback; //将回调函数添加到事件列表中 可以理解为添加订阅公众号人数,并为每个订阅者提供通知服务
  return callbackIndex; // 返回订阅者id 可以理解为是第几个订阅的人
};

// 发布
EventBus.prototype.$emit = function(key, ...args) {
  const EventList = this.eventObj[key]; // 获取本次发布内容对应的所有订阅者
  Object.keys(EventList).forEach((fnKey) => {
    EventList[fnKey](...args); // 执行传入的函数  可以理解为挨个通知所有订阅者本次发布的内容
    if (fnKey.indexOf("once") > -1) {
      // 只执行一次的订阅 执行完就删除
      delete EventList[fnKey];
    }
  });
};

// 取消
EventBus.prototype.$off = function(key, id) {
  delete this.eventObj[key][id]; // 删除订阅事件 可以理解为取消通知订阅者
  if (this.eventObj[key].length === 0) {
    // 如果没人关注公众号 就删除该事件
    delete this.eventObj[key];
  }
};

// 执行一次
EventBus.prototype.$once = function(key, callback) {
  if (this.eventObj[key] === undefined) {
    // 未订阅过该事件
    this.eventObj[key] = {};
  }
  const callbackIndex = this.callbackId++; // 先赋值再添加 每添加一个订阅者 人数加1
  this.eventObj[key]["once" + callbackIndex] = callback; //将回调函数添加到事件列表中 可以理解为添加订阅公众号人数,并为每个订阅者提供通知服务,使用once标记只订阅一条消息的订阅者
  return callbackIndex; // 返回订阅者id 可以理解为是第几个订阅的人
};

code verification

Next, we use a few examples to verify the functions of these implementations.
1. Publish, subscribe

const eventBus = new EventBus();

eventBus.$on("gongzhonghao1", (content) => {
  console.log(`用户1订阅了gongzhonghao1,${content}`);
});
eventBus.$on("gongzhonghao1", (content) => {
  console.log(`用户2订阅了gongzhonghao1,${content}`);
});
eventBus.$emit("gongzhonghao1", "文章内容1");
eventBus.$emit("gongzhonghao1", "文章内容2");

The official account posted two messages, and both users received two messages.
insert image description here

unsubscribe

const eventBus = new EventBus();

eventBus.$on("gongzhonghao1", (content) => {
  console.log(`用户1订阅了gongzhonghao1,${content}`);
});
const id = eventBus.$on("gongzhonghao1", (content) => {
  console.log(`用户2订阅了gongzhonghao1,${content}`);
});

eventBus.$emit("gongzhonghao1", "文章内容1");

eventBus.$off('gongzhonghao1', id)  

eventBus.$emit("gongzhonghao1", "文章内容2");

Unsubscribed from the official account before posting the second message, so user 2 only received the first post from official account 1
insert image description here

3. Subscribe once


const eventBus = new EventBus();

eventBus.$on("gongzhonghao1", (content) => {
  console.log(`用户1订阅了gongzhonghao1,${content}`);
});
 eventBus.$once("gongzhonghao1", (content) => {
  console.log(`用户2订阅了gongzhonghao1,${content}`);
});

eventBus.$emit("gongzhonghao1", "文章内容1");


eventBus.$emit("gongzhonghao1", "文章内容2");

User 2 has only subscribed to the content once, so cannot receive the second message

insert image description here

reference article

# Interviewer: Please write an EventBus by hand, let me see your coding ability!

Guess you like

Origin blog.csdn.net/Salange1/article/details/127523376