📕
blog
  • Hi there
  • javascript
    • 柯里化 - Curry
    • 观察者和订阅-发布模式
    • generator
    • 发布订阅-依赖于window
    • pwa manual trigger install
  • browser
    • beautify scrollbar
  • http
    • nginx 缓存配置
  • extra
    • vue-cli 不使用 .env[.xxx] 文件,添加额外运行时参数
    • docker-compose nginx with ssl config
  • React
    • How React works
Powered by GitBook
On this page
  • 观察者模式
  • 订阅-发布模式

Was this helpful?

  1. javascript

观察者和订阅-发布模式

观察者模式


class Observe {
  constructor() {
    this.events = []
  }

  subscribe(func){
    if(this.events.includes((func)))return
    this.events.push(func)
  }

  unsubscribe(func){
    const index = this.events.findIndex(func)
    if(index!==-1){
      this.events.splice(index, 1)
    }
  }

  notify(...args){
    this.events.forEach(func=>{
      func.apply(args)
    })
  }
}

// test case

const observe = new Observe()
observe.subscribe((...args)=>{
  console.log(`this is first subject `,args)
})
observe.subscribe((...args)=>{
  console.log(`this is second subject `,args)
})

observe.notify('memeda')

result

this is first subject Array(0)

this is second subject Array(0)

订阅-发布模式

type EventHandler = (payload:any) => void

class EventEmitter {
  private events = new Map<string,EventHandler[]>()

  subscribe(topic:string,...handlers:EventHandler[]):EventHandler[]{
    let topics = this.events.get(topic)
    if(topics){
      topics.push(...handlers)
    }else{
      topics = [...handlers]
      this.events.set(topic, topics)
    }
    return topics
  }

  unsubscribe (topic:string, handler?:EventHandler):boolean {
    let IS_OK = false
    const topics = this.events.get(topic)
    if(topics){
      if(handler){
        const index = topics.findIndex(func=>func===handler)
        if(index!==-1){
          topics.splice(index,1)
          IS_OK = true
        }else{
          IS_OK = false
        }
      }else{
        this.events.delete(topic)
      }
    }else{
      IS_OK = false
    }
    return IS_OK
  }

  notify(topic:string,...args:any[]){
    const topics = this.events.get(topic)
    if(topics){
      topics.forEach(handler=>{
        handler(args)
      })
    }
  }
}

const eventEmitter:EventEmitter = new EventEmitter()

const handler = payload => {
  console.log('blog updated, content is :', payload)
}

eventEmitter.subscribe('update:blog',handler)

eventEmitter.notify('update:blog', 'this is sync task')

setTimeout(()=>{
  eventEmitter.notify('update:blog','macrotask update')
},0)

Promise.resolve().then(()=>{
  eventEmitter.notify('update:blog','microtask update')
})

requestAnimationFrame(()=>{
  eventEmitter.notify('update:blog','requestAnimationFrame update')
})


setTimeout(()=>{
  const isOk = eventEmitter.unsubscribe('update:blog',handler)
  console.log('times up, unsubscribe result is :',isOk)
  eventEmitter.notify('update:blog','macrotask update in 10 second')
},3*1000)

result

blog updated, content is : ["this is sync task"] app.ts:51

blog updated, content is : ["microtask update"] app.ts:51

blog updated, content is : ["requestAnimationFrame update"] app.ts:51

blog updated, content is : ["macrotask update"] app.ts:73

times up, unsubscribe result is : true

Previous柯里化 - CurryNextgenerator

Last updated 4 years ago

Was this helpful?