Skip to main content

第 22 章:Lane 优先级模型——31 条车道

第 5 章说 Scheduler 有五级优先级。但 React 内部需要更细的区分:同样是一个 setState,在 onClick 里调和在 useEffect 里调,紧迫程度不一样。所以 React 不用五级,而是用一套 31 位的位图模型,叫 Lane(车道)。

先记住这一句:Lane 就是一个 31 位的二进制数,每一位是一条"车道",数字越小(越靠低位)优先级越高。多条更新用或运算合并成 Lanes,取最高优先就找最低的 1

一图流:31 条车道怎么分组

位图:为什么用二进制

ReactFiberLane.js 里,总车道数是 31(ReactFiberLane.js:40)。每个常量是一个二进制位:

export const SyncLane: Lane = 0b0000000000000000000000000000010; // 第 46 行
export const InputContinuousLane: Lane = 0b0000000000000000000000000001000;
export const DefaultLane: Lane = 0b0000000000000000000000000100000;

用位图的好处是所有优先级操作都是 O(1) 位运算

  • 合并多条更新:mergeLanes(a, b) = a | b。一次点击里的多个 setState 各占一个位,| 一下就到一起。
  • 判断某条更新是否在里面:(lanes & lane) !== 0
  • 取最高优先级:找最低位的 1,getHighestPriorityLanelanes & -lanes(lowestOneBit)直接拿到。

这三个操作在第 21 章的旅程里无处不在:requestUpdateLane 要一个位,scheduleUpdateOnFiber 把位写到 lanesgetNextLanes 决定这一轮渲染哪些位。

车道分组:从最急到最不急

按优先级从高到低,车道分成几组:

车道组bit 范围用途
Sync(第 46 行)1同步更新,flushSync
InputContinuous(第 50 行)3输入类(onClick、onChange),Scheduler 的 UserBlocking
Default(第 53 行)5普通 setState,Scheduler 的 Normal
Transition(第 61 行)8~23,16 条useTransition 里的低优先更新,每条 transition 一条车道
Retry(第 93 行)24~27,4 条Suspense 挂起后的重试
SelectiveHydration / Idle / Offscreen(101~108 行)28~30水合、空闲任务、隐藏树

低位是"用户正等着看结果"的事(点击、输入),高位是"可以慢慢来"的事(低优先 transition、预加载)。lane 和 Scheduler 五级优先级之间有个换算:React 把 lane 映射成 Scheduler 的优先级再排队(第 5 章那个对接),lane 是 React 自己的"精确刻度",Scheduler 是"粗粒度执行器"。

并发怎么靠 lane 工作

lane 是第 23 章(并发渲染)的地基:一次渲染带着一组 lanes 开跑,中途来了更高优先级的 lane,就中断当前渲染,先渲染新 lane 那批。渲染完了检查还有没有更高优先的 lane,没有才 commit。getNextLanes 每次问"现在该跑哪些车道",答案就是这一轮 render 的路线图。

动手实验

  1. 看 requestUpdateLane:在 requestUpdateLane(ReactFiberLane.js 附近)打断点,分别从 onClickuseEffectsetState,观察两次拿到的 lane 不同(前者 InputContinuous,后者 Default)。
  2. 看合并:一个事件里连调两次 setState,观察 fiber 的 lanes 变成两个位的或。
  3. 看取最高:在 getNextLanes 打断点,同一批里混着 Sync 和 Default 的更新,看它是不是先挑了 Sync。

小结

  • Lane 是 31 位位图,低 bit 高优先,所有操作是 O(1) 位运算。
  • 分组:Sync / InputContinuous / Default / Transition×16 / Retry×4 / Idle / Offscreen。
  • mergeLanes(或)、getHighestPriorityLane(lowest bit)、getNextLanes(选路线图)。
  • lane 是 React 的精确刻度,Scheduler 是粗粒度执行器,两者换算对接。
  • 下一步:lane 让"中断和恢复"成为可能,第 23 章看并发渲染。