美文网首页
vue.js设计与实现(四)-响应系统-避免无限递归循环

vue.js设计与实现(四)-响应系统-避免无限递归循环

作者: 幸宇 | 来源:发表于2023-01-08 15:52 被阅读0次

在上述程序代码中可能会出现如下问题:
我在effect函数中定义一个如下的自增加代码:

 effect(
        function effectFn1(){
            obj.foo++
        }
    )

结果如下:


image.png

该结果是栈的益处,原因是:
首先读取 obj.foo 的值,这会触发 track 操作,将当前副作用函数收集到“桶”中,接着将其加 1 后再赋值给 obj.foo,此时会触发 trigger 操作,即把“桶”中的副作用函数取出并执行。但问题是该副作用函数正在执行中,还没有执行完毕,就要开始下一次的执行。这样会导致无限递归地调用自己,于是就产生了栈溢出。

解决办法并不难。通过分析这个问题我们能够发现,读取和设置操作是在同一个副作用函数内进行的。此时无论是 track 时收集的副作用函数,还是 trigger 时要触发执行的副作用函数,都是 activeEffect。基于此,我们可以在 trigger 动作发生时增加守卫条件:如果 trigger 触发执行的副作用函数与当前正在执行的副作用函数相同,则不触发执行,如以下代码所示:

function trigger(target,key){
        let depsMap = bucket.get(target)
        if(!depsMap) return
        const effects=depsMap.get(key)
        const effectsToRun = new Set()
        effects && effects.forEach(effectFn=>{
            if(effectFn!==activeEffect){
                effectsToRun.add(effectFn)
            }
        })
        effectsToRun.forEach(effect=>effect())
    }

这样我们就能够避免无限递归调用,从而避免栈溢出。

相关文章

网友评论

      本文标题:vue.js设计与实现(四)-响应系统-避免无限递归循环

      本文链接:https://www.haomeiwen.com/subject/jkmtcdtx.html