美文网首页
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