发布订阅

300 阅读1分钟

发布订阅模式:是模拟DOM2级事件的事件池思想,在某一个时刻到来时,我们要做很多的事情(很多函数)。我们准备一个数组当做一个事件池,并且提供向事件池中加入函数的方法以及移除的方法,当时刻来临时,我们把事件池中的方法取出来挨个执行;

发布订阅:

订阅:订阅该时刻到来,把想做的事情加入事件池 发布:时刻真的到来了,把事件池中的方法都执行了

// 准备事件池:
let ary = [];

function addListener(fn) {
  if (ary.includes(fn)) return;
  ary.push(fn)
}
function removeListener(fn) {
  // 数组.filter 方法,把数组中满足条件的(回调函数返回true的项)组成一个新数组,原数组不变;
  ary = ary.filter(item => item !== fn);
}
function fire() {
  ary.forEach(item => item())
}

function fn1(_this) {
  console.log(1)
}
function fn2() {
  console.log(3)
}
function fn3() {
  console.log(3)
}

// 订阅5s后的这个时刻
add(fn1);
add(fn2);
add(fn3);

// 取消订阅
removeListener(fn3);

setTimeout(function () {
  // 5s后时刻来临,就把事件池中的方法都执行了
  fire(this);
}, 5000);

封装发布订阅

class Subscribe {
  constructor () {
    this.pond = [];
  }
  includes (fn) {
    // 判断当前事件池是否包含某一个函数
    return this.pond.includes(fn);
  }
  addListener (fn) {
    // 不能重复添加
    if (!this.includes(fn)) this.pond.push(fn);
    return this;
  }
  removeListener (fn) {
    // 取消订阅
    if (this.includes(fn)) {
      this.pond = this.pond.filter(item => item !== fn);
    }
    return this;
  }
  fire (...args) {
    // 等到时刻到来时把事件池中的的函数都执行了
    this.pond.forEach(item => item(...args));
  }
}


function fn1() {
  console.log(1)
}
function fn2() {
  console.log(2)
}
function fn3() {
  console.log(3)
}

let plan = new Subscribe();

plan.addListener(fn1).addListener(fn2).addListener(fn3);

setTimeout(() => plan.fire([1, 2, 3]), 5000);