锦囊(代码实现)

124 阅读2分钟

1.发布订阅模式与观察者模式的代码实现

发布订阅模式

class PubSub {
  constructor() {
    this.events = {}
  }
  subscribe(event, callback) {
    // 订阅事件
    if (this.events[event]) {
      this.events[event].push(callback)
    } else {
      this.events[event] = [callback]
    }
  }
  publish(event, ...args) {
    // 发布消息,触发对应的回调
    const subscribeEvents = this.events[event]
    if (subscribeEvents && subscribeEvents.length) {
      subscribeEvents.forEach(callback => {
        callback.call(this, ...args)
      })
    }
  }
  unsubscribe(event, callback) {
    // 删除某个订阅,保留其他订阅
    const subscribeEvents = this.events[event]
    if (subscribeEvents && subscribeEvents.length) {
      this.events[event] = this.events[event].filter(cb => cb !== callback)
    }
  }
}

使用:(可以解决回调地狱)

const request = require("request");
const pubSub = new PubSub();

request('https://www.baidu.com', function (error, response) {
  if (!error && response.statusCode == 200) {
    console.log('get times 1');
    // 发布请求1成功消息
    pubSub.publish('request1Success');
  }
});

// 订阅请求1成功的消息,然后发起请求2
pubSub.subscribe('request1Success', () => {
  request('https://www.baidu.com', function (error, response) {
    if (!error && response.statusCode == 200) {
      console.log('get times 2');
      // 发布请求2成功消息
      pubSub.publish('request2Success');
    }
  });
})

// 订阅请求2成功的消息,然后发起请求3
pubSub.subscribe('request2Success', () => {
  request('https://www.baidu.com', function (error, response) {
    if (!error && response.statusCode == 200) {
      console.log('get times 3');
      // 发布请求3成功消息
      pubSub.publish('request3Success');
    }
  });
})

观察者模式

class Observe {
  constructor() {
    this.state = ''
    this.observes = []
  }
  getState() {
    return this.state
  }
  setState(state) {
    this.state = state
    this.notify()
  }
  addObserve(observe) {
    this.observes.push(observe)
  }
  notify() {
    this.observes.forEach(observe => observe.update())
  }
}
class Watcher {
  constructor(name, sub) {
    this.name = ''
    this.sub = sub
    this.sub.addObserve(this)
  }
  update() {
    console.log(this.sub.getState())
  }
}
var sub = new Observe()
var a = new Watcher('a', sub)
var b = new Watcher('b', sub)
sub.setState('3') //3,3

观察者模式与发布订阅模式的区别在于:

  • 观察者模式是一个主题对应多个观察者,主题更新了,会告诉所有的观察者
  • 发布订阅模式是,多个事件(主题),一个事件对应多个观察者。发布订阅模式中,可以自己定义事件的名称,去更新订阅了对应事件的观察者,而观察者模式就只有一个主题,不能够自定义事件名称。

DOM自定义事件:

原理应该是通过事件冒泡机制进行传递的。

//创建一个event对象
let event = document.createEvent("HTMLEvents");
//自定义事件名 是否冒泡 是否阻止默认事件
event.initEvent("autoEventName",true,false)
//监听事件
document.addEventListener("autoEventName",(e)=>{
    console.log(e)
})
//派发这个事件
document.dispatchEvent(event)