React 调和阶段的中断实现机制

1. 概述

React 16 引入的新调和引擎(Fiber Reconciler)最重要的特性之一就是可中断的渲染过程。这个特性让 React 能够将渲染工作分割成多个小块,并且能够暂停和恢复渲染过程,从而提供更好的用户体验。

2. Fiber 架构

2.1 什么是 Fiber

Fiber 是 React 16 中新的协调引擎。它的主要目标是启用虚拟 DOM 的增量渲染。

  • Fiber 是一种数据结构,代表一个工作单元

  • 每个 React 元素都对应一个 Fiber 节点

  • Fiber 节点构成了一个链表树结构

2.2 Fiber 节点的结构

javascript 复制代码
type Fiber = {

// 标记不同类型的节点

tag: WorkTag,

// 节点的唯一标识

key: null | string,

// 节点的类型信息

type: any,

// 当前节点的状态

stateNode: any,

  


// Fiber 树结构

return: Fiber | null,

child: Fiber | null,

sibling: Fiber | null,

  


// 工作单元

pendingProps: any,

memoizedProps: any,

updateQueue: UpdateQueue<any> | null,

};

3. 时间切片(Time Slicing)

3.1 基本原理

时间切片的核心思想是将长任务分割成小片段,每个片段的执行时间都很短,从而不会阻塞主线程。

javascript 复制代码
const ENOUGH_TIME = 1; // 假设 1ms 就需要让出主线程

  


let deadline = 0;

  


const shouldYield = () => {

return performance.now() >= deadline;

};

  


const workLoop = (hasTimeRemaining) => {

while (nextUnitOfWork && hasTimeRemaining) {

nextUnitOfWork = performUnitOfWork(nextUnitOfWork);

if (shouldYield()) {

// 时间片到期,中断执行

break;

}

}

};

3.2 requestIdleCallback

React 使用 requestIdleCallback(在生产环境使用自己实现的调度器)来调度任务:

javascript 复制代码
requestIdleCallback((deadline) => {

// deadline.timeRemaining() 返回当前帧还剩余的时间

while (deadline.timeRemaining() > 0 && nextUnitOfWork) {

nextUnitOfWork = performUnitOfWork(nextUnitOfWork);

}

});

4. 调度优先级

4.1 优先级划分

React 的调度优先级从高到低:

  1. Immediate:立即执行的优先级

  2. UserBlocking:用户交互的优先级

  3. Normal:正常优先级

  4. Low:低优先级

  5. Idle:空闲优先级

4.2 优先级实现

javascript 复制代码
const priorityLevel = {

ImmediatePriority: 1,

UserBlockingPriority: 2,

NormalPriority: 3,

LowPriority: 4,

IdlePriority: 5

};

  


function scheduleCallback(priorityLevel, callback) {

const currentTime = getCurrentTime();

const timeout = getTimeoutForPriority(priorityLevel);

const expirationTime = currentTime + timeout;

  


const newTask = {

callback,

priorityLevel,

expirationTime,

// ...

};

  


// 将任务加入优先级队列

addTaskToQueue(newTask);

}

5. 中断机制的实现

5.1 工作循环

javascript 复制代码
function workLoopConcurrent() {

while (workInProgress !== null && !shouldYield()) {

workInProgress = performUnitOfWork(workInProgress);

}

}

  


function performUnitOfWork(unitOfWork) {

// 1. 执行当前工作单元

const current = unitOfWork.alternate;

let next = beginWork(current, unitOfWork, renderExpirationTime);

  


// 2. 完成当前工作单元

if (next === null) {

next = completeUnitOfWork(unitOfWork);

}

  


return next;

}

5.2 中断和恢复

当时间片用完时,React 会:

  1. 保存当前工作进度

  2. 让出主线程

  3. 等待下一个时间片

  4. 从上次中断的地方继续执行

javascript 复制代码
function renderRoot(root, isYieldy) {

do {

try {

workLoop(isYieldy);

break;

} catch (thrownValue) {

// 错误处理

}

} while (true);

  


if (isYieldy && workInProgress !== null) {

// 还有工作要做,但时间片已用完

return RootIncomplete;

} else {

// 所有工作完成

return RootCompleted;

}

}

6. 总结

React 的可中断渲染机制是通过以下几个关键点实现的:

  1. Fiber 架构提供了可分割的最小工作单元

  2. 时间切片机制确保了渲染过程不会长期占用主线程

  3. 优先级调度系统保证了重要的更新能够优先执行

  4. 完善的中断和恢复机制确保了渲染过程的连续性

这种机制让 React 能够在保持响应性的同时,处理复杂的渲染任务,从而提供更好的用户体验。

相关推荐
抱抱宝4 小时前
Agent-study项目教程(03):手写 Mini-ReAct Agent(不依赖框架)
javascript·人工智能·gpt·react.js·prompt·agent
想要成为糕糕手9 小时前
🚀 在浏览器里跑 DeepSeek-R1?WebGPU 端侧推理实战(六)—— 完结篇:消息渲染与流式收尾
react.js·typescript·llm
YIAN10 小时前
从 Hash 底层原理到 React Router v6 实战:我学会了什么?
前端·react.js·vue-router
YUS云生11 小时前
大模型学习·第46天:Agent智能体核心概念与ReAct框架
前端·学习·react.js
To_OC11 小时前
后端接口还没交付,前端如何独立把整套业务跑通
前端·react.js·全栈
程序员跑路13 小时前
Barrel Export、Jest、Babel 与依赖图
react.js
l1m0_13 小时前
告别反复修改Prompt:AI生成React应用并落地开发的实战复盘
前端·react.js·ui·ai·设计
xexpertS14 小时前
前端工程转型实践:从 Ember 迁移到 React,提升构建速度与研发效能
前端·react.js·前端框架
张元清15 小时前
React useFocus Hook:追踪并控制元素焦点状态 (2026)
javascript·react.js
一朵好运莲16 小时前
智能体使用 Chrome DevTools MCP 调试浏览器
开发语言·javascript·react.js