天天看点

最近使用过的发布订阅模式

       之前写小程序,然后遇到个登录过期的问题,由于小程序页面只要是在栈中,就可以一直运行,所以,通过登录过期这个事件的发布,使所有订阅了这个消息的页面进行一些操作,可以省去一些麻烦

       这里写了个简单可用的发布订阅,在项目里面使用也很简单,直接放在 globalData 里面供全局所有页面使用

// 发布订阅
class MyEvent {
  constructor () {
    this.events = {}
  }
  // 添加事件监听
  on (type, fn) {
    if (!this.events[type]) {
      this.events[type] = []
    }
    this.events[type].push(fn)
  }
  // 触发事件 例:fire('click', 1)
  fire () {
    let [type, ...otherArgs] = [...arguments]
    let fnArray = this.events[type]
    if (!fnArray) return false
    for (let i = 0; i< fnArray.length; i++) {
      if (typeof fnArray[i] !== 'function') {
        // 检测到当前项不是函数,删除并继续下一次循环
        fnArray.splice(i, 1)  // 这里删除已经移除的函数
        i--
        continue
      }
      fnArray[i](...otherArgs)
    }
  }
  // 去除监听的某个回调 例:off('click', fn)
  off () {
    let [type, fn] = [...arguments]
    console.log(type, fn)
    let fnArray = this.events[type]
    
    for (let i = 0; i < fnArray.length; i++) {
      console.log(fnArray[i] === fn)
      if (fnArray[i] === fn) {
        // 删除回调函数
        /*
        不在这里使用 splice 去删除方法,是为了防止数组塌陷,
        在 fire 执行过程中跳过了对某一个方法的执行,所以在这里假移除,
        然后在 fire 方法那里再把它移除掉
        */
        fnArray[i] = null
        break
      }
    }
  }
}

module.exports = MyEvent
           

       发布消息:

app.globalData.ev.fire('logout')           // 发送登出通知
           

       订阅消息:

app.globalData.ev.on('logout', this.handleLogout)
           

继续阅读