当前位置: 首页 > news >正文

【React源码解析】深入剖析Scheduler源码

Scheduler调度

React中,有一个单独的Scheduler库专门用于处理上面讨论的时间切片。

我们简单看一下Scheduler关键源码实现:

  1. 首先,在 packagegs/react-reconciler/src/ReactFiberWorkLoop.new.js 文件中:
// 循环更新 fiber 节点
function workLoopConcurrent() {while (workInProgress !== null && !shouldYield()) {// 更新单个 fiber 节点performUnitOfWork(workInProgress);}
}

在更新时,如果是Concurrent模式,低优先级更新会进入到workLoopConcurrent函数。该函数的作用就是遍历Fiber节点,创建Fiber树并标记哪些Fiber被更新了。performUnitOfWork表示的是对每个Fiber节点的处理操作,每次处理前都会执行shouldYield()方法,下面看一下shouldYield

  1. 其次,在 packages/scheduler/src/forks/Scheduler.js文件中:
export const frameYieldMs = 5;
let frameInterval = frameYieldMs;function shouldYieldToHost() {const timeElapsed = getCurrentTime() - startTime;// 判断时间间隔是否小于 5msif (timeElapsed < frameInterval) {return false;}...
}

shouldYield()方法会去判断累计更新的时间是否超过5ms

  1. 最后,在 packages/scheduler/src/forks/Scheduler.js文件中:
let schedulePerformWorkUntilDeadline;
if (typeof localSetImmediate === 'function') {schedulePerformWorkUntilDeadline = () => {localSetImmediate(performWorkUntilDeadline);};
} else if (typeof MessageChannel !== 'undefined') {const channel = new MessageChannel();const port = channel.port2;channel.port1.onmessage = performWorkUntilDeadline;schedulePerformWorkUntilDeadline = () => {port.postMessage(null);};
} else {schedulePerformWorkUntilDeadline = () => {localSetTimeout(performWorkUntilDeadline, 0);};
}

如果超过了5ms,就会通过schedulePerformWorkUntilDeadline开启一个宏任务进行下一个更新。这里react做了兼容的处理,实际上是优先使用MessageChannel而不是setTimeout,这是因为在浏览器帧中MessageChannel更优先于setTimeout执行。

总的来说,Scheduler库的处理和前面讨论的时间切片类似。事实上,浏览器也正在做同样的Scheduler库做的事情:通过内置一个api——scheduler.postTask 来解决用户交互在某些情况下无法即时相应的问题,有兴趣的话可以看看相关内容。

最终,通过这种时间切片的方式,在浏览器下的performance面板中,会呈现出如下渲染过程:原本一个耗时的更新(如渲染10000li标签),被分割为一个个5ms的小更新:
image.png

到这里,我们已经清楚了如何让一个耗时的更新不去阻塞用户事件和渲染了。但是这只是有一个更新任务的情况,如果在React更新一半时,click事件进来,然后执行click事件回调,并且触发了新的更新,那么该如何处理共存的两个更新呢?如果click事件的更新过程中,又有其他的click事件触发更新呢?这就涉及到多个更新并存的情况,这也是我们接下来需要讨论的点。


http://www.mrgr.cn/news/25068.html

相关文章:

  • 【课程系列12】某客时间AI大模型微调训练营
  • 数据结构C //线性表(链表)ADT结构及相关函数
  • 企业四要素核验是什么?如何应用
  • 函数题 6-2 多项式求值【PAT】
  • 3款数据恢复免费版软件评测:帮你轻松解决数据丢失问题
  • 代码设计:如何处理配置文件
  • 【阅读文献】一个使用大语言模型的端到端语音概要
  • 主导Instagram的10家企业
  • Java常见异常及Spring Validation框架详解
  • 为什么苹果智能为AI隐私设立了新的黄金标准
  • Subclass-balancing Contrastive Learning for Long-tailed Recognition核心思想讲解
  • 【直播预告】从人工智能到类脑与量子计算:数学与新计算范式
  • 浅谈机器视觉中面光源和点光源的区别
  • DOS-CMD 常用命令介绍
  • pptp解说
  • Leetcode题解精讲之二叉树的基本理论(分类、四种遍历方式、存储方式)
  • Claude Artifacts 全面开放:探索AI设计的无限可能
  • 笔记:Centos Jdk Nginx 安装包安装命令
  • 非结构化数据中台的用户权限管理
  • 小白学 RAG:Milvus 介绍与使用教程