依赖追踪
我们如何去理解依赖这个概念呢?
我们定义一个叫Dep类,这个类有两个方法,一个是depend,一个是notify。 depend用于收集依赖,即把依赖这个状态的代码(也就是回调函数)保存起来。 notify用于将之前收集到的所有依赖代码,重新执行。
然后我们会定义一个函数autoRun(),这个函数用于接收一个更新函数,当我们执行autoRun()时,会执行传入的更新函数,并保存更新函数,当notify被调用时,会重新执行更新函数。
练习:实现依赖追踪
js
class Dep {
// TODO:补充完整
}
function autoRun() {
// TODO:补充完整
}
const dep = new Dep()
autoRun(() => {
dep.depend()
console.log('updated!')
})
// 输出日志: "updated!"
dep.notify() // 输出日志: "updated!"答案
js
let activeUpdate = null
class Dep {
constructor() {
this.subscribers = new Set()
}
depend() {
if(activeUpdate) {
this.subscribers.add(activeUpdate)
}
}
notify() {
this.subscribers.forEach(sub => sub())
}
}
function autoRun(update) {
function wrapUpdate() {
activeUpdate = update
update()
activeUpdate = null
}
wrapUpdate()
}
const dep = new Dep()
autoRun(() => {
dep.depend()
console.log('updated!')
})
// 输出日志: "updated!"
dep.notify() // 输出日志: "updated!"执行顺序就是:
- 实例化
Dep - 调用
autoRun() - 将传入
autoRun()的更新函数update()保存到变量activeUpdate,然后执行更新函数update() - 执行更新函数时,会执行
dep.depend()实现依赖保存(也就是把更新函数保存到subscribers集合中),然后将activeUpdate重置为空 - 接下来开始调用
dep.notify(),把subscribers集合中所有的依赖(更新函数)重新执行一遍; - 需要注意的是,这次执行更新函数时,虽然也调用了
dep.depend(),但由于activeUpdate为空,所以依赖没有重复保存,然后就直接执行了console.log('updated!')
如此我们便成功实现了依赖追踪。