React不使用requestIdleCallback实现调度原理解析

 更新时间:2022年11月28日 11:02:08   作者:用户6816925221619  
这篇文章主要为大家介绍了React不使用requestIdleCallback实现调度原理解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

1.起因

最近在一边啃源码,一边手写fiber嘛,然后也看了很多博客和资料,基本上大伙好像都是说用requestIdleCallback来模拟react实现一个空闲时间调度。但我自己手写的时候把怎么用怎么怪,老是感觉有什么地方不对劲而且是在调度过程中,可能是因为我是想写出来来一个相对健全一点的模版方便我以后写源码的其他部分把,然后分析了一下所以有了这篇博客。

2.查找问题

1.requestIdleCallback是利用帧之间空闲时间来执行JS,它是一个低优先级的处理策略它给我的感觉就是做一些类似上报之类的操作,但实际上Fiber的构建以及渲染内容,并不算是一个低优先级任务。

2.兼容性这个就总所周知了,这个api并不适合在生产环境上。

3.requestIdleCallback实际上是在布局和绘制之后,那意味在也许你在里面做的事情(可能是通过数据修改触发dom修改)会重排。可以看看这个试验

3.解决问题

所以这时候我们就可以回到源码中去看,react是怎么实现的,源码地址

核心调度实现

    // 有执行任务
    if (scheduledHostCallback !== null) {
      const currentTime = getCurrentTime();
      // 计算一帧的过期时间点
      deadline = currentTime + yieldInterval;
      const hasTimeRemaining = true;
      try {
        // 执行c回调
        const hasMoreWork = scheduledHostCallback(
          hasTimeRemaining,
          currentTime,
        );
        // 执行完该回调后, 判断后续是否还有其他任务
        if (!hasMoreWork) {
          isMessageLoopRunning = false;
          scheduledHostCallback = null;
        } else {
          // 还有其他任务, 推进进入下一个宏任务队列中
          port.postMessage(null);
        }
      } catch (error) {
        // If a scheduler task throws, exit the current browser task so the
        // error can be observed.
        port.postMessage(null);
        throw error;
      }
    } else {
      isMessageLoopRunning = false;
    }
    // Yielding to the browser will give it a chance to paint, so we can
    // reset this.
    // 重置状态
    needsPaint = false;
  };

  const channel = new MessageChannel();
  // port2 发送
  const port = channel.port2;
  // port1 接收
  channel.port1.onmessage = performWorkUntilDeadline;
  // 在每一帧中执行任务
  requestHostCallback = function(callback) {
    // 回调注册
    scheduledHostCallback = callback;
    if (!isMessageLoopRunning) {
      isMessageLoopRunning = true;
      // 进入宏任务队列
      port.postMessage(null);
    }
  };
  // 取消回调
  cancelHostCallback = function() {
    scheduledHostCallback = null;
  };
  // 设置超时回调
  requestHostTimeout = function(callback, ms) {
    taskTimeoutID = setTimeout(() => {
      callback(getCurrentTime());
    }, ms);
  };
  // 取消超时
  cancelHostTimeout = function() {
    clearTimeout(taskTimeoutID);
    taskTimeoutID = -1;
  };

代码里的注释写得很清楚了把,但有几个点可以说一下。

1.首先选择宏任务,因为我们需要去及时的让出主线程(微任务并不会让出主线程也是在更新页面前去执行)。

2.其次是宏任务中的选择,MessageChannel,setTimeout,requestAnimationFrame,都是宏任务,setTimeout会浪费4ms(这个大伙可以去看看),requestAnimationFrame的触发时间是不稳定的(可以看看浏览器的更新页面机制),所以我猜想最后就选了MessageChannel把。

4.总结

其实到这思路也比较明了了,把React中为什么不使用requestIdleCallback理清楚,还顺便把React的核心调度原理看了一下。

5.吐槽

唉,其实看源码和手写源码完全是两种感觉,更多的是体现在实现细节和代码耦合性健壮性的问题,写是怎么写都行,但如何写优雅的方便人迭代的代码就好烧脑。比如你就想实现一个fiber的大体思路就不难,但是如果想你在fiber上加hook,难度几何飙升,基础构建和细节实现就很重要了,手写肯定是不等于抄,还需要在里面加写自己的想法和如何简化的方案。

以上就是React不使用requestIdleCallback实现调度原理解析的详细内容,更多关于React不使用requestIdleCallback调度的资料请关注脚本之家其它相关文章!

相关文章

  • 一篇文章介绍redux、react-redux、redux-saga总结

    一篇文章介绍redux、react-redux、redux-saga总结

    这篇文章主要介绍了一篇文章介绍redux、react-redux、redux-saga总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-05-05
  • react-pdf 打造在线简历生成器的示例代码

    react-pdf 打造在线简历生成器的示例代码

    本文主要介绍了react-pdf 打造在线简历生成器的示例代码,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • useState 解决文本框无法输入的问题详解

    useState 解决文本框无法输入的问题详解

    这篇文章主要为大家介绍了useState 解决文本框无法输入的问题详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • 详解Ref在React中的交叉用法

    详解Ref在React中的交叉用法

    众所周知,react推出了hooks之后,很多项目就开始往hooks上靠拢,所以也就出现了class和hooks交叉使用的项目。这个时候使用ref需要注意一些东西
    2021-06-06
  • React报错之组件不能作为JSX组件使用的解决方法

    React报错之组件不能作为JSX组件使用的解决方法

    本文主要介绍了React报错之组件不能作为JSX组件使用的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • React翻页器的实现(包含前后端)

    React翻页器的实现(包含前后端)

    本文主要介绍了React翻页器的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • 基于react后端渲染模板引擎noox发布使用

    基于react后端渲染模板引擎noox发布使用

    本篇文章主要介绍了基于react后端渲染模板引擎noox发布使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • react的ui库antd中form表单使用SelectTree反显问题及解决

    react的ui库antd中form表单使用SelectTree反显问题及解决

    这篇文章主要介绍了react的ui库antd中form表单使用SelectTree反显问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • 解析TypeError:import_react_native.AppState.removeEventListener is not a function

    解析TypeError:import_react_native.AppState.removeEventListener

    这篇文章主要为大家介绍了TypeError:import_react_native.AppState.removeEventListener is not a function问题解决分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • React Context详解使用方法

    React Context详解使用方法

    Context提供了一个无需为每层组件手动添加props,就能在组件树间进行数据传递的方法。在一个典型的 React 应用中,数据是通过props属性自上而下(由父及子)进行传递的,但这种做法对于某些类型的属性而言是极其繁琐的
    2022-12-12

最新评论