一三零、使用react Fiber原理优化页面渲染卡死问题

一、页面卡顿分析

在浏览器中,js 线程和渲染线程共用一个主线程
遇到一些复杂的计算任务时,JavaScript 运行时间过长,就会阻塞渲染线程上的任务,导致掉帧

优化方案有很多:

  • 拆分计算任务,匀到多帧
  • 通过 worker 开启多线程计算
  • 采用 wasm 加速计算

二、拆分计算任务,匀到多帧

React是怎么做的?

  • React 在页面更新时,会自顶向下计算 virtual dom 上的不同处。如果计算任务耗时过长,渲染线程在 16 ms 中无法执行任务,页面会出现掉帧/卡死现象。
  • React Fiber 解决这个问题的思路是把渲染/更新过程(递归diff)拆分成一系列小任务。每次检查树上的一小部分,做完看是否还有时间继续下一个任务,有的话继续,没有的话把自己挂起,主线程不忙的时候再继续

Demo

执行下面的代码,浏览器会有10s左右的时间处于卡死状态:无法滚动、无法编辑、无法关闭tab

      function repeat(str, count){
    
    
           let result = ''
           for(let i = 0; i < count; i++){
    
    
               result += str
           }
         return result;
      } 
       console.log(repeat('1', 9999999))

按照 fiber 的设计思想,拆分计算任务,来解决页面卡死的问题

    const repeat = (str, count) => {
    
    
        let maxLoopCount = 999999;
        async function runTask(count, cb) {
    
    
            let taskStr = '';
            let taskResult = new Promise((rs) => {
    
    
            	// window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行
                window.requestAnimationFrame(() => {
    
    
                    for (let i = 0; i < count && i < maxLoopCount; i++) {
    
    
                        taskStr += str;
                    }
                    // 拆分任务 每次执行的任务不大于maxLoopCount
                    if (count > maxLoopCount) {
    
    
                        runTask(count - maxLoopCount, (restValue) => {
    
    
                            cb && cb(taskStr + restValue);
                            rs(taskStr + restValue);
                        });
                    } else {
    
    
                        cb && cb(taskStr);
                        rs(taskStr);
                    }
                });
            });
            return taskResult;
        }
        return runTask(count);
    };
    repeat('1', 999999999).then((result) => console.log(result));

总结

  • js 线程如果占用主线程太长时间,会影响页面本身的渲染任务
  • 通过拆分 js 任务,保证在不影响渲染进程的前提下,实现js复杂任务的计算

猜你喜欢

转载自blog.csdn.net/zm06201118/article/details/116784866
今日推荐