恭喜你,你知道了React Scheduler和React Fiber的原理

239 阅读2分钟
  • 浏览器一个瞬间只能有一个线程在执行,很自然地,有一个问题:有长任务怎么办,执行很长时间的一段代码,唯一线程不能做任何其他事情,在100ms内也不会响应用户操作,卡死了。
    function abcd(){
        console.log('A') // 假定需要 50ms
        console.log('B') // 假定需要 50ms
        console.log('C') // 假定需要 50ms
        console.log('D') // 假定需要 50ms
    }
  • 现在有一个很自然的想法,就是我能不能把这个长任务分割成多个小任务来执行,执行完了一个小任务之后,把线程让出去,先让别人用,让UI响应用户的操作,用户是爷爷,你先响应用户操作,这样自然就不会卡。 这个时候,你需要知道一个重要的信息:定时器可以让出线程
    function a(){
        console.log("A")
    }
    setTimeout(a,250)

这段code的意思是:在250ms之后向任务队列插入一个执行a function的任务,在这个时间点之前,其他所有UI更新和javascript都可以执行,不影响响应用户操作

  • 整理一下我们的想法,可以有:
    function a(){
        console.log("A")
    }
    function b(){
        console.log("B")
    }
    function c(){
        console.log("C")
    }
    function d(){
        console.log("D")
    }
    setTimeout(a,250)
    setTimeout(b,250*2)
    setTimeout(c,250*3)
    setTimeout(d,250*4)

整理一下:

    setTimeout(function(){
        a();
        setTimeout(function(){
            b()
            setTimetout(function(){
                c();
                setTimetout(function(){
                    d()
                },250)
            },250)
        },250)
    },250)

这样的代码太丑陋了,这个时候,我们需要知道一种【数组模式】,可以更简洁,把所有的任务依次放在一个数组里,依次取出来依次执行

    function a(){
        console.log("A")
    }
    function b(){
        console.log("B")
    }
    function c(){
        console.log("C")
    }
    function d(){
        console.log("D")
    }
    const tasks = [a,b,c,d]
    function execute(){
        let task = tasks.shift();
        task();
        if(tasks.length>0){
            setTimeout(execute,250)
        }
    }
    execute()

把setTimetout替换成requestIdleCallback(facebook有一个更好的实现)

    function a(){
        console.log("A")
    }
    function b(){
        console.log("B")
    }
    function c(){
        console.log("C")
    }
    function d(){
        console.log("D")
    }
    const tasks = [a,b,c,d]
    function execute(){
        let task = tasks.shift();
        task();
        if(tasks.length>0){
            requestIdleCallback(execute)
        }
    }
    execute()

恭喜你,你知道了React Scheduler和React Fiber引入的原理。React Fiber和Scheduler引入的本质原因是分割长任务,按照重要程度依次执行。