fat-cat

lanes (车道模型)类型任务的位掩码优先级体系

从值的角度来看,位掩码就是一个二进制数。所谓的「lane」就是只有一位为 1,其他位都是 0 的二进制数;而「lanes」就是有多个位为 1,其他位都是 0 的二进制数(31 位)。

用十进制值表示任务优先级存在两个不足点

lane 的生命周期可以分为几个阶段:

react 在每一次创建 update 对象之前都会做一个动作:请求一条 lane - requestUpdateLane()

// react@18.2.0/packages/react-reconciler/src/ReactFiberWorkLoop.old.js
function requestUpdateLane(fiber) {
  // Special cases
  const mode = fiber.mode;

  if ((mode & ConcurrentMode) === NoMode) {
    return SyncLane;
  } else if (
    (executionContext & RenderContext) !== NoContext &&
    workInProgressRootRenderLanes !== NoLanes
  ) {
    // This is a render phase update. These are not officially supported. The
    // old behavior is to give this the same "thread" (lanes) as
    // whatever is currently rendering. So if you call `setState` on a component
    // that happens later in the same render, it will flush. Ideally, we want to
    // remove the special case and treat them as if they came from an
    // interleaved event. Regardless, this pattern is not officially supported.
    // This behavior is only a fallback. The flag only exists until we can roll
    // out the setState warning, since existing code might accidentally rely on
    // the current behavior.
    return pickArbitraryLane(workInProgressRootRenderLanes);
  }

  const isTransition = requestCurrentTransition() !== NoTransition;

  if (isTransition) {
    // updates at the same priority within the same event. To do this, the
    // inputs to the algorithm must be the same.
    //
    // The trick we use is to cache the first of each of these inputs within an
    // event. Then reset the cached values once we can be sure the event is
    // over. Our heuristic for that is whenever we enter a concurrent work loop.

    if (currentEventTransitionLane === NoLane) {
      // All transitions within the same event are assigned the same lane.
      currentEventTransitionLane = claimNextTransitionLane();
    }

    return currentEventTransitionLane;
  } // Updates originating inside certain React methods, like flushSync, have
  // their priority set by tracking it with a context variable.
  //
  // The opaque type returned by the host config is internally a lane, so we can
  // use that directly.
  // TODO: Move this type conversion to the event priority module.

  const updateLane = getCurrentUpdatePriority();

  if (updateLane !== NoLane) {
    return updateLane;
  } // This update originated outside React. Ask the host environment for an
  // appropriate priority, based on the type of event.
  //
  // The opaque type returned by the host config is internally a lane, so we can
  // use that directly.
  // TODO: Move this type conversion to the event priority module.

  const eventLane = getCurrentEventPriority();
  return eventLane;
}


react 是这样生产 lane 的:

鉴于 react 对这些「常量 lane 的赋值」和「lane 的值越小,则代表优先级越高」的定性,那么从优先级比较的角度出发,我们可以得到这样的结论:

离散型事件中触发的更新请求的优先级 >
连续型事件中触发的更新请求的优先级 >
其他 DOM 事件中触发的更新请求的优先级 =
react 外部方法中触发的更新请求的优先级 >
startTransition 中触发的更新请求的优先级

React 按照事件的紧急程度,把它们划分成三个等级: