React调度器原理
- 1、react的调度是通过Scheduler包,是独立的包,独自承担起任务调度的作用
- 2、将任务和任务的优先级交给Scheduler调度,它就可以帮你管理任务,安排任务的执行
对于多个任务,它会先执行优先级高的。对于单个任务,它会有节制地去执行。换句话说,线程只有一个,它不会一直占用着线程去执行任务。而是执行一会,中断一下,如此往复。用这样的模式,来避免一直占用有限的资源执行耗时较长的任务,解决用户操作时页面卡顿的问题,实现更快的响应
- 3、任务优先级让任务按照自身的紧急程度排序,让优先级最高的任务最先被执行到
- 4、Scheduler调度有2个核心功能:任务队列管理、时间切片【可中断和恢复】
- 5、单个任务的中断以及恢复
- 如果某个任务执行时间过长,达到了时间片限制的时间,那么该任务必须中断,以便于让位给更重要的事情
- 执行时间分割, 让出主线程(把控制权归还浏览器, 浏览器可以处理用户输入, 浏览器绘制等紧急任务)
分析源码
React的调度过程可以在packages/scheduler包中找到,包含了调度器的核心逻辑,用于管理React中的任务调度
Scheduler.js:这个文件包含了调度器的主要逻辑,包括任务调度的入口点和处理器。SchedulerWork.js:这个文件定义了任务的各种状态,如未开始、挂起、暂停等。SchedulerPriorities.js:这个文件定义了React调度中的不同优先级,如ImmediatePriority、UserBlockingPriority和NormalPriority等
react调度有几种优先级
Scheduler的优先级级别,它为任务定义了以下几种级别的优先级:
-
如果算上NoPriority 这个表示没有优先级为0,算上那就一共为6种,否则5种
-
react的Scheduler调度一共有6种优先级 【0 - 5】
源码位置:packages\scheduler\src\SchedulerPriorities.js
export const NoPriority = 0; // 没有任何优先级
export const ImmediatePriority = 1; // 立即执行的优先级,级别最高
export const UserBlockingPriority = 2; // 用户阻塞级别的优先级
export const NormalPriority = 3; // 正常的优先级
export const LowPriority = 4; // 较低的优先级
export const IdlePriority = 5; // 优先级最低,表示任务可以闲置
说说调度流程
- 1、任务入队:当有任务需要执行时,React将任务添加到任务队列中,根据任务的优先级进行排队
- 2、调度:调度器会定期检查任务队列,并根据任务的优先级决定哪个任务应该被执行。更高优先级的任务会在更低优先级的任务之前执行
- 3、执行任务:调度器选择下一个要执行的任务,并将其传递给执行器进行处理
- 4、任务完成:一旦任务执行完成,React会更新相关的组件状态,然后继续下一个任务
- 5、任务中断:如果有更高优先级的任务进入队列,调度器可以中断当前正在执行的任务,以执行更高优先级的任务
任务如何打断
React调度器支持任务的中断,以确保更高优先级的任务能够及时执行。当更高优先级的任务进入任务队列时,它可以打断当前正在执行的任务。React中的任务打断是通过调度器(Scheduler)和React Fiber架构来实现的
-
React Fiber
-
一个 fiber 就是一个 JavaScript 对象
-
是虚拟DOM的增量式渲染,可以把一个大的渲染任务分为很多小阶段,按照优先级来执行这些任务分片,优先级高的会先执行
-
每个Fiber节点都有一个优先级属性
-
每个React组件都对应一个Fiber节点
-
1、任务入队:当有新的任务需要执行时,React将创建相应的Fiber节点,并将它们加入任务队列
- 按照优先级排序
2、任务调度:React调度器周期性地检查任务队列中的Fiber节点,并根据它们的优先级决定哪个任务应该被执行。这是通过requestIdleCallback或requestAnimationFrame等浏览器API来触发的。React会根据浏览器的空闲时间来安排任务
3、任务执行:调度器选择下一个要执行的Fiber节点,并将其传递给执行器(performUnitOfWork)
4、任务打断:当更高优先级的任务进入任务队列时,React可以中断当前正在执行的任务
这是通过在performUnitOfWork中的协作(cooperative)方式来实现的。具体的步骤如下:
- 执行器执行当前Fiber节点的任务,但在完成任务前检查是否有更高优先级的任务。
- 如果有更高优先级的任务,执行器会停止当前任务,并将控制权交给调度器,以便调度器可以重新安排任务。
- 调度器会根据新任务的优先级重新计算任务队列的优先级顺序,并选择下一个要执行的Fiber节点。
- 执行器会回到任务队列,继续执行下一个Fiber节点的任务。