React Fiber的调度算法你了解多少呢?

React Fiber 的调度算法是 React 架构中最核心的部分之一,它是为了支持 可中断、可恢复、可优先级排序的更新 而设计的调度系统。


🧠 React Fiber 调度算法的核心理念

React Fiber 的调度算法是一个 "cooperative scheduling"(合作调度) 模型,它让渲染过程变成了可中断的工作单元,从而可以让浏览器在必要时打断 React,让出主线程以响应用户交互。


🧩 Fiber 架构基本概念

Fiber 是什么?

  • React Fiber 是一个工作单元(Work Unit)
  • 每个 Fiber 节点对应一个组件实例
  • 每次更新都是在构建一棵新的 Fiber 树

Fiber 树的遍历过程分为两个阶段:

  1. render 阶段(工作阶段) :构建新的 Fiber 树,生成副作用列表(effect list)。此阶段是可中断的
  2. commit 阶段(提交阶段) :执行副作用,如 DOM 操作。此阶段是同步的、不可中断的

🔁 调度算法核心流程

一、任务调度入口

scss 复制代码
ReactDOM.createRoot(container).render(<App />);

每次更新(比如 setState、useState)都会被封装为一个**任务(Task)**加入任务队列,由调度器统一处理。


二、任务优先级:Lane 模型(React 18 引入)

  • **Lane(车道)**是 Fiber 用来标识任务优先级的一种机制。

  • 不同更新对应不同的 Lane,如:

    • SyncLane(同步)
    • InputContinuousLane(连续用户输入)
    • DefaultLane(默认)
    • TransitionLane(过渡动画)
    • IdleLane(空闲)

多个 Lane 可以组合在一起,形成并发调度策略


三、工作循环(Work Loop)

1. scheduleUpdateOnFiber(fiber)

  • 在组件中调用 setStatedispatch 时触发
  • 把该 Fiber 节点所在的根节点标记为"有更新"
  • 提交到调度器进行调度(例如调用 ensureRootIsScheduled

2. performConcurrentWorkOnRoot(root)

  • 检查当前任务是否过期
  • 执行 render 阶段的 work loop

3. workLoopConcurrent()

  • 类似一个 while 循环:遍历 Fiber 树,执行每个节点的工作单元
  • 每次循环都会检查浏览器是否有更高优先级任务需要处理
ini 复制代码
while (workInProgress !== null && !shouldYield()) {
  workInProgress = performUnitOfWork(workInProgress);
}

shouldYield() 是通过 scheduler 提供的 requestIdleCallback/MessageChannel 模拟的,用于判断是否中断。


四、执行每个单元:performUnitOfWork(fiber)

ini 复制代码
function performUnitOfWork(fiber) {
  const next = beginWork(fiber);
  if (next === null) {
    completeUnitOfWork(fiber);
  } else {
    return next;
  }
}
  • beginWork:构建子节点(虚拟 DOM)
  • completeUnitOfWork:回溯并收集副作用(effect list)

这两个函数递归遍历整棵树(DFS)。


五、render 完成后 → 进入 commit 阶段

当所有 Fiber 节点遍历完成,进入同步的 commit 阶段:

scss 复制代码
commitRoot(root);

commit 包括三个子阶段:

  1. beforeMutation(如生命周期 getSnapshotBeforeUpdate)
  2. mutation(如 DOM 插入、删除)
  3. layout(如 useLayoutEffect)

⚙️ Scheduler 调度器简介

React 的调度器(scheduler 包)是 React 自己实现的一套任务优先队列系统,模拟浏览器空闲时间运行任务。

主要功能:

  • 时间分片(Time Slicing)
  • 任意任务优先级调度(优先处理重要更新)
  • 模拟浏览器调度行为

使用:

scss 复制代码
unstable_scheduleCallback(priorityLevel, callback);

🪜 优先级分类(Lane 与 Scheduler 优先级对应关系)

Lane 示例 对应 Scheduler 优先级
SyncLane setState in click Immediate
InputContinuousLane 输入 UserBlocking
DefaultLane 默认更新 Normal
TransitionLane startTransition Low
IdleLane 无时间限制的更新 Idle

🎯 总结流程图(简化版)

scss 复制代码
用户操作触发更新(setState)
        ↓
scheduleUpdateOnFiber
        ↓
requestIdleCallback / MessageChannel
        ↓
performConcurrentWorkOnRoot
        ↓
render阶段 (Fiber 树遍历) [可中断]
        ↓
commit阶段 (DOM 更新) [同步执行]

✅ Fiber 调度算法的优势

优点 说明
可中断更新 避免主线程卡顿
可分片执行 利用 requestIdleCallback / MessageChannel 分帧处理
支持优先级调度 用户交互优先于动画、过渡等
渲染暂停与恢复 比如页面在后台不渲染,返回再恢复

相关推荐
Scabbards_2 分钟前
CPT304-2425-S2-Software Engineering II
前端
小满zs7 分钟前
Zustand 第二章(状态处理)
前端·react.js
程序猿小D9 分钟前
第16节 Node.js 文件系统
linux·服务器·前端·node.js·编辑器·vim
萌萌哒草头将军12 分钟前
🚀🚀🚀Prisma 发布无 Rust 引擎预览版,安装和使用更轻量;支持任何 ORM 连接引擎;支持自动备份...
前端·javascript·vue.js
狼性书生26 分钟前
uniapp实现的简约美观的星级评分组件
前端·uni-app·vue·组件
书语时29 分钟前
ES6 Promise 状态机
前端·javascript·es6
拉不动的猪1 小时前
管理不同权限用户的左侧菜单展示以及权限按钮的启用 / 禁用之其中一种解决方案
前端·javascript·面试
西陵1 小时前
前端框架渲染DOM的的方式你知道多少?
前端·javascript·架构
小九九的爸爸1 小时前
我是如何让AI帮我还原设计稿的
前端·人工智能·ai编程
海的诗篇_1 小时前
前端开发面试题总结-JavaScript篇(一)
开发语言·前端·javascript·学习·面试