发布订阅模式、事件轮询

326 阅读3分钟

一、发布订阅模式

一般用来处理大型项目(框架)的封装

自行搜索:vue2.0响应式实现原理

案例:去书店买书

JS 曾经的流程

  • 1.你去到书店,问店员有没有一本叫做《JS从入门到入土》

  • 2.店员:我们现在没有,你下次再来吧

  • 3.过一段时间后,又去书店问店员 有没有一本叫做《JS从入门到入土》

  • 4.店员:我们现在没有,你下次再来吧

  • 5.过一段时间后,又去书店问店员 有没有一本叫做《JS从入门到入土》

  • 6.店员:我们现在没有,你下次再来吧

  • ……

  • 89.过一段时间后,又去书店问店员 有没有一本叫做《JS从入门到入土》

  • 90.店员:在XX位置有,你去拿吧

发布订阅模式:

  • 1.你去到书店,问店员有没有一本叫做《JS从入门到入土》

  • 2.店员:我们现在没有,然后你留下一个联系方式,将来有了之后我电话通知你

  • 3.过了一段时间,有书本了,电源通过电话联系到你,触发了你的技能(触发了一个函数),然后购买了书本

  • 'JS从入门到入土':[预约1, 预约2,预约3],

  • '颈椎病的预防':[预约1, 预约2,预约3]

    class observer {
      constructor(name) {
        this.name = name //模拟店员的名字,但是不重要
        this.msgList = {} //模拟店员的记录手册
      }

      // 购买不到书本,留下预约方式的时候执行
      add(type, fn) {
        // 通过这个函数可以向 this.magList 内添加内容,后续方便维护

        if (this.msgList[type] === undefined) { //当前分支执行,表明这个type是第一次出现
          this.msgList[type] = [] //在第一次出现的时候,给它赋值一个空数组,后续的内容直接 push 到数组内就可以了
        }

        this.msgList[type].push(fn)
      }

      // 一段时间后,书本到了,通知对应的预约者,然后触发他们的技能(函数)
      tri(type) {
        this.msgList[type].forEach(item => item()) //通过传入的 type 找到对应的属性值,然后遍历调用内部所有的函数
      }

      delName(type, fn) {
        // 调用这个方法,取消预约,找到对应的数组,将你的练习方式删掉

        this.msgList[type] = this.msgList[type].filter(item => item !== fn)
      }
    }

    const o1 = new observer('小刚')
    console.log(o1);

    // 书名
    const bookName1 = 'JS从入门到入土'
    const bookName2 = '颈椎病的预防'

    // 预约者的技能(函数)
    const fnA = () => console.log('我是张三,我想购买这本书')
    const fnB = () => console.log('我是李四,我想购买这本书')
    const fnC = () => console.log('我是王五,我想购买这本书')

    // 新增两位预约者
    o1.add(bookName1, fnA)
    o1.add(bookName1, fnB)
    o1.add(bookName1, fnC)

    // 中间一位预约者取消了预约
    o1.delName(bookName1, fnB)

    // 过了一段时间后,书本到了,通知对应的预约者来购买
    o1.tri(bookName1)
    console.log('有预约者之后的对象:', o1);

二、事件轮询

时间:

  • 从开始执行代码开始执行轮询

规则:

  • 从 JS 整体代码开始(这是一个宏任务)

  • 每执行完毕一个宏任务,就会清空一次微任务(不管微任务队列里有多少任务,都执行完毕)

  • 再次执行下一个宏任务

  • 循环往复,直到所有的任务队列清空结束

关键字:

  • 1.单线程:JS 是一个单线程的代码执行机制,逐行向下执行,上边的代码执行时间过长会阻塞下边的代码

  • 2.调用栈:用来执行代码的,所有的代码进栈执行,执行完毕再出栈(后进先出

  • 3.队列:用来存放异步任务的,先进先出

    • 宏任务队列:JS整体代码,setTimeout,setInterval...
    • 微任务队列:promise.then()...
  • 4.轮询:轮流询问 宏任务与微任务队列的任务来执行

  • 5.注意:WEBApi,用来负责提供异步机制,计时,分配任务去指定队列

最关键的一句话:每执行完毕一个任务,会清空一次微任务队列(前提是你要区分清楚什么是同步任务,什么是宏任务,什么是微任务)