一、发布订阅模式
一般用来处理大型项目(框架)的封装
自行搜索: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()...
- 宏任务队列:JS整体代码,
-
4.轮询:轮流询问 宏任务与微任务队列的任务来执行
-
5.注意:WEBApi,用来负责提供异步机制,计时,分配任务去指定队列
最关键的一句话:每执行完毕一个任务,会清空一次微任务队列(前提是你要区分清楚什么是同步任务,什么是宏任务,什么是微任务)