react 怎么获取img 的src_react源码个人笔记-版本17.0.0(笔记04)

本文深入解析了React中如何处理更新调度,包括同步更新、异步更新和优先级处理。通过一系列函数如`scheduleUpdateOnFiber`、`ensureRootIsScheduled`、`scheduleSyncCallback`等,详细阐述了React内部如何决定何时执行`performSyncWorkOnRoot`或`performConcurrentWorkOnRoot`。同时,文章也探讨了不同优先级的任务调度和时间管理,如`requestHostCallback`、`handleTimeout`和`workLoop`的工作机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

b245c7f1e72738ae4880cc5cf6ef7ce3.png

// ensureRootIsScheduled 函数定义(1)

// src: src/react/packages/react-reconciler/src/ReactFiberWorkLoop.old.js
// 逻辑:  修改调度开始,(1) 当update 为同步,非批量更新, 时间为非(render  || commit) 
// 走performSyncWorkOnRoot ,(2)其他调度走 ensureRootIsScheduled
// 确认下一次调度callback的lanes, 判断是否有未完成的callback, 新旧callback判断,是否取消
// 1 同步任务: scheduleSyncCallback 2, 批量同步: scheduleCallback 3, 异步任务: 
// scheduleCallback, 并设置最新的callback 和优先级
function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {
  // 已经存在的callbackNode
  const existingCallbackNode = root.callbackNode;  // 已经存在的callbackNode
  // Check if any lanes are being starved by other work. If so, mark them as
  // expired so we know to work on those next.
  //  将(1)已经过期的Lane 添加到root.expiredLanes 上, 
// (2)pingedLanes 或 非suspendedLanes  设置时间
  markStarvedLanesAsExpired(root, currentTime);
  // Determine the next lanes to work on, and their priority.
  // lanes 由workInProgressRoot 确定, 非空取workInProgressRootRenderLanes, 
// 否则NoLanes 获取nextLanes
  const nextLanes = getNextLanes(root, root === workInProgressRoot
 ? workInProgressRootRenderLanes : NoLanes);
//   root === workInProgressRoot 是否已经开始调度了, 调度开始,赋值,结束清空
  // This returns the priority level computed during the `getNextLanes` call.
// 下一个回调的优先级确认
  const newCallbackPriority = returnNextLanesPriority();
    // 特殊情况, noting to working on 
  if (nextLanes === NoLanes) {
    // Special case: There's nothing to work on.
    if (existingCallbackNode !== null) {
      cancelCallback(existingCallbackNode);
      root.callbackNode = null;  // 清空任务
      root.callbackPriority = NoLanePriority;  // 清空优先级
    }
    return;
  }

  // Check if there's an existing task. We may be able to reuse it.
  //  节点存在, 任务存在
  if (existingCallbackNode !== null) {
    // 优先级
    const existingCallbackPriority = root.callbackPriority;
    if (existingCallbackPriority === newCallbackPriority) { // 相同 优先级相同
      // The priority hasn't changed. We can reuse the existing task. Exit.
      // 直接返回
      return;
      // 优先级相同, 跳过,保留当前任务
    }
    // The priority changed. Cancel the existing callback. We'll schedule a new
    // one below.
    // 有其他级任务进来, 取消任务, 高等级或低等级都取消
    cancelCallback(existingCallbackNode);
  }
  // Schedule a new callback.
  let newCallbackNode;  // 新的callbackNode
  // 同步优先级
  if (newCallbackPriority === SyncLanePriority) { // SyncLanePriority 15
    // Special case: Sync React callbacks are scheduled on a special
    // internal queue
    newCallbackNode = scheduleSyncCallback(
      performSyncWorkOnRoot.bind(null, root),  // 有方法
    );
  } else if (newCallbackPriority === SyncBatchedLanePriority) { 
    //  14  SyncBatchedLanePriority: 14
    // 同步批量优先级
    newCallbackNode = scheduleCallback(
      ImmediateSchedulerPriority,  // 立即
      performSyncWorkOnRoot.bind(null, root),  // 有方法
    );
  } else {
    // 异步优先级, 获取对应的优先级
    const schedulerPriorityLevel = lanePriorityToSchedulerPriority(
      newCallbackPriority,
    );
    // 调度工作, 创建 newCallbackNode
    newCallbackNode = scheduleCallback(
      schedulerPriorityLevel,
      performConcurrentWorkOnRoot.bind(null, root),
    );
    // 
  }
  // 回调函数的优先级, 当前的优先级更高
  root.callbackPriority = newCallbackPriority;  // 最新的callback优先级
  root.callbackNode = newCallbackNode;  // 挂载最新的callbackNode
  // 回调函数的enode
}

// markStarvedLanesAsExpired 函数定义(2)

// url: src/react/packages/react-reconciler/src/ReactFiberLane.js
// 逻辑:获取当前的时间和rootFiber 上的pendingLanes ,循环遍历所有的lane, 进行比较,如果已经过期,将Lane 添加到
// expiredLanes 上, 是非suspendedLanes 或pingedLanes,且expirationTime 添加时间
export function markStarvedLanesAsExpired(
  root: FiberRoot,
  currentTime: number,  // 当前时间
): void {
  // TODO: This gets called every time we yield. We can optimize by storing
  // the earliest expiration time on the root. Then use that to quickly bail out
  // of this function.
  // 最早的过期时间在 root 上, 
  const pendingLanes = root.pendingLanes; // pendingLanes 
  const suspendedLanes = root.suspendedLanes; // suspendedLanes
  const pingedLanes = root.pingedLanes;  // pingedLanes
  const expirationTimes = root.expirationTimes;  // expirationTimes
// expirationTimes 时间数组,31个元素,对应update 添加的时间
 
  // 遍历pendingLanes, 确认已经达到过期时间, 
  let lanes = pendingLanes;
  // 数值 > 0
  while (lanes > 0) {  // 单个单个的遍历
    // 从左往右 进行遍历
    const index = pickArbitraryLaneIndex(lanes);  // 
    const lane = 1 << index;  // 获取对应的位置的l您tuhlane  // // shi hishi时间
    // 对应的时间
    const expirationTime = expirationTimes[index];
    // 为空, 
    if (expirationTime === NoTimestamp) {
      // Found a pending lane with no expiration time. If it's not suspended, or
      // if it's pinged, assume it's CPU-bound. Compute a new expiration time
      // using the current time.
      // 是非suspendedLanes 或pingedLanes,且expirationTime 添加时间
      if (
        (lane & suspendedLanes) === NoLanes ||
        (lane & pingedLanes) !== NoLanes
      ) {
        // Assumes timestamps are monotonically increasing.
        //  重新设置时间
        expirationTimes[index] = computeExpirationTime(lane, currentTime);
      }
    } else if (expirationTime <= currentTime) { // 时间已经过期
      // This lane expired
      root.expiredLanes |= lane;  // 已经过期的lans 增加 对应的lane
  // 添加已经过期的lane
    }

    lanes &= ~lane; // 循环遍历
  }
}

// 获取当前的更新的位数
function pickArbitraryLaneIndex(lanes: Lanes) {
  // 获取当前lans, 实际数据为 (31 - lans 左侧开始零的个数)
  return 31 - clz32(lanes);
}
// 32 减去 非零数字左侧的0 的个数
const clz32 = Math.clz32 ? Math.clz32 : clz32Fallback;

const log = Math.log;
const LN2 = Math.LN2;
function clz32Fallback(lanes: Lanes | Lane) {
  if (lanes === 0) {
    return 32;
  }
  return (31 - ((log(lanes) / LN2) | 0)) | 0;
}

// computeExpirationTime 函数定义(3)

// 计算过期时间  lane  时间
//  url : src/react/packages/react-reconciler/src/ReactFiberLane.js
// 逻辑: 从当前的lane和时间获取一个新的ExpirationTime, 在markStarvedLanesAsExpired 调用
// 特定的lane, 为pingedLanes ,且非suspendedLanes , 且当前ExpirationTime 为空, 重新计算
function computeExpirationTime(lane: Lane, currentTime: number) {
  // TODO: Expiration heuristic is constant per lane, so could use a map.
  getHighestPriorityLanes(lane);  // 
// 10-15
  const priority = return_highestLanePriority;  // 获取优先级
  if (priority >= InputContinuousLanePriority) { // 10-15
    return currentTime + 250;
  } else if (priority >= TransitionPriority) { //  6-9
    //  TransitionPriority: 6
    return currentTime + 5000;
  } else {
    // Anything idle priority or lower should never expire.
    return NoTimestamp;  // -1
  }
}

// return_highestLanePriority 全局变量
export const SyncLanePriority: LanePriority = 15; // 同步?
export const SyncBatchedLanePriority: LanePriority = 14;  // 同步批量?
const InputDiscreteHydrationLanePriority: LanePriority = 13; // 输入离散混合?
export const InputDiscreteLanePriority: LanePriority = 12;  // 输入离散?
const InputContinuousHydrationLanePriority: LanePriority = 11; // 输入连理混合?
export const InputContinuousLanePriority: LanePriority = 10;  // 输入连续?
const DefaultHydrationLanePriority: LanePriority = 9; // 默认混合?
export const DefaultLanePriority: LanePriority = 8; // 默认?
const TransitionHydrationPriority: LanePriority = 7; // transition 混合?
export const TransitionPriority: LanePriority = 6;  // transition?
const RetryLanePriority: LanePriority = 5;  // 再次?
const SelectiveHydrationLanePriority: LanePriority = 4; // 选择?
const IdleHydrationLanePriority: LanePriority = 3;  // 混合?
const IdleLanePriority: LanePriority = 2;?
const OffscreenLanePriority: LanePriority = 1;  // 屏幕?推测?
export const NoLanePriority: LanePriority = 0;  // 没有??
const TotalLanes = 31; // ?

// getHighestPriorityLanes 函数定义(4)

// 获取最高优先级的lane
// url src/react/packages/react-reconciler/src/ReactFiberLane.js
// 逻辑: 获取当前最高的lane
function getHighestPriorityLanes(lanes: Lanes | Lane): Lanes {
  // 1 非批量同步
  if ((SyncLane & lanes) !== NoLanes) {  // 1  
    return_highestLanePriority = SyncLanePriority;  // 15  16-1
    return SyncLane;  // 1
  }
  // 批量同步
  if ((SyncBatchedLane & lanes) !== NoLanes) {  // 2
    return_highestLanePriority = SyncBatchedLanePriority;  // 14  // 16-2
    return SyncBatchedLane;
  }
  // 输入离散混合? click?
  if ((InputDiscreteHydrationLane & lanes) !== NoLanes) {  // 4
    return_highestLanePriority = InputDiscreteHydrationLanePriority;  // 13
    return InputDiscreteHydrationLane;
  }
  // 输入离散
  const inputDiscreteLanes = InputDiscreteLanes & lanes; // 24
  if (inputDiscreteLanes !== NoLanes) {
    return_highestLanePriority = InputDiscreteLanePriority;  // 12
    return inputDiscreteLanes;
  }
  // 输入连续 混合
  //  0b0000000000000000000000000100000
  if ((lanes & InputContinuousHydrationLane) !== NoLanes) {
    return_highestLanePriority = InputContinuousHydrationLanePriority;
    return InputContinuousHydrationLane;
  }
// 输入连续
  const inputContinuousLanes = InputContinuousLanes & lanes;
  if (inputContinuousLanes !== NoLanes) {
    return_highestLanePriority = InputContinuousLanePriority;
    return inputContinuousLanes;
  }
// 默认耦合
  if ((lanes & DefaultHydrationLane) !== NoLanes) {
    return_highestLanePriority = DefaultHydrationLanePriority;
    return DefaultHydrationLane;
  }
  const defaultLanes = DefaultLanes & lanes;
  if (defaultLanes !== NoLanes) {
    return_highestLanePriority = DefaultLanePriority;
    return defaultLanes;
  }
  if ((lanes & TransitionHydrationLane) !== NoLanes) {
    return_highestLanePriority = TransitionHydrationPriority;
    return TransitionHydrationLane;
  }
  const transitionLanes = TransitionLanes & lanes;
  if (transitionLanes !== NoLanes) {
    return_highestLanePriority = TransitionPriority;
    return transitionLanes;
  }
  const retryLanes = RetryLanes & lanes;
  if (retryLanes !== NoLanes) {
    return_highestLanePriority = RetryLanePriority;
    return retryLanes;
  }
  if (lanes & SelectiveHydrationLane) {
    return_highestLanePriority = SelectiveHydrationLanePriority;
    return SelectiveHydrationLane;
  }
  if ((lanes & IdleHydrationLane) !== NoLanes) {
    return_highestLanePriority = IdleHydrationLanePriority;
    return IdleHydrationLane;
  }
  const idleLanes = IdleLanes & lanes;
  if (idleLanes !== NoLanes) {
    return_highestLanePriority = IdleLanePriority;
    return idleLanes;
  }
  if ((OffscreenLane & lanes) !== NoLanes) {
    return_highestLanePriority = OffscreenLanePriority;
    return OffscreenLane;
  }

  // This shouldn't be reachable, but as a fallback, return the entire bitmask.
  return_highestLanePriority = DefaultLanePriority; /// DefaultLanePriority : 8 默认
  return lanes;
}

//. getNextLanes 函数定义(5)

// 定义 getNextLanes , 当前的root , lanes : 0
// 位置: src/react/packages/react-reconciler/src/ReactFiberLane.js
// 逻辑: 找寻下一个lane
// 定义 getNextLanes , 当前的root , lanes : 0
export function getNextLanes(root: FiberRoot, wipLanes: Lanes): Lanes {
  // Early bailout if there's no pending work left.
  // 获取pendingLanes
  const pendingLanes = root.pendingLanes;  // 1 等待的lane
  if (pendingLanes === NoLanes) { // 为0
    return_highestLanePriority = NoLanePriority; // 0
    return NoLanes; // 0
  }

  let nextLanes = NoLanes;  // 0    // 下一个更新的nextLanes
  let nextLanePriority = NoLanePriority;  // 0 // 下一个更新的优先级

  const expiredLanes = root.expiredLanes; // 0 // 当前的expiredLanes
  const suspendedLanes = root.suspendedLanes; // 0 // 当前的suspendedLanes
  const pingedLanes = root.pingedLanes; // 0 // 当前的pingedLanes
  // pendingLanes 非空
  // Check if any work has expired.
  // 检查任务是否过期了, 存在过期的任务
  if (expiredLanes !== NoLanes) {  // 是否有任务过期
    nextLanes = expiredLanes; // 设置过期的任务有过期
    nextLanePriority = return_highestLanePriority = SyncLanePriority;  // 15
  } else {
    // 无任务过期的情况
    // Do not work on any idle work until all the non-idle work has finished,
    // even if the work is suspended.
     // 在完成所有非空闲工作之前,请勿进行任何闲置工作,即使工作是suspended。
    // const NonIdleLanes = 0b0000111111111111111111111111111;
    // 就是去除  等IdleHydrationLane, IdleLanes, OffscreenLane 的任务
    const nonIdlePendingLanes = pendingLanes & NonIdleLanes;  // 获取非IdleLanes
    if (nonIdlePendingLanes !== NoLanes) { // 非空
      // suspendedLanes :0
   //    非pendingLanes , 如nonIdlePendingLanes 与当前的suspendedLanes 是否无交集
      const nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes;  // 非pendingLanes
      // 且非suspendedLanes 任务
      if (nonIdleUnblockedLanes !== NoLanes) { // 无j
        // nonIdleUnblockedLanes: 1
        nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes);  // 1
        nextLanePriority = return_highestLanePriority;   // 15
      } else {
        // nonIdlePendingLanes  就是suspendedLanes 任务
        const nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes;
        // 且是pingedLanes
        if (nonIdlePingedLanes !== NoLanes) {
          nextLanes = getHighestPriorityLanes(nonIdlePingedLanes);
          nextLanePriority = return_highestLanePriority;
        }
      }
    } else {
     
      // The only remaining work is Idle.
       // 只剩下空闲的工作 如 IdleHydrationLane, IdleLanes, OffscreenLane
      const unblockedLanes = pendingLanes & ~suspendedLanes;
      // 且不是suspendedLanes
      if (unblockedLanes !== NoLanes) {
        nextLanes = getHighestPriorityLanes(unblockedLanes);
        nextLanePriority = return_highestLanePriority;
      } else {
        // 如果是suspendedLanes
        if (pingedLanes !== NoLanes) {
          nextLanes = getHighestPriorityLanes(pingedLanes);
          nextLanePriority = return_highestLanePriority;
        }
      }
    }
  }
  // 只有我们是suspended才能到达这里
  if (nextLanes === NoLanes) {

    // 只有我们是suspended才能到达这里
    // This should only be reachable if we're suspended
    // TODO: Consider warning in this path if a fallback timer is not scheduled.
    return NoLanes;
  }

  // If there are higher priority lanes, we'll include them even if they
  // are suspended.
    // 如果有更高优先级的lanes,我们将包含他们即便他们是suspended
  nextLanes = pendingLanes & getEqualOrHigherPriorityLanes(nextLanes);
  // 1
  // pendingLanes
  // If we're already in the middle of a render, switching lanes will interrupt
  // it and we'll lose our progress. We should only do this if the new lanes are
  // higher priority.
    // 如果我们已经在渲染中间,切换lanes将会中断他并且我们会失去我们的进度
  // 我们只能在新的更高优先级的lanes中做这些
// 传入的lanns 非空, 且不等于nextLanes
  if (
    wipLanes !== NoLanes &&
    wipLanes !== nextLanes &&
    // If we already suspended with a delay, then interrupting is fine. Don't
    // bother waiting until the root is complete.
     // 如果我们已经suspended了一段时间,那么中断就可以了。别等到根完成为止。
    (wipLanes & suspendedLanes) === NoLanes
  ) {
    getHighestPriorityLanes(wipLanes);
    const wipLanePriority = return_highestLanePriority;
    if (nextLanePriority <= wipLanePriority) {
      return wipLanes;
    } else {
      return_highestLanePriority = nextLanePriority;
    }
  }

 
  // time we apply the entanglement.
  const entangledLanes = root.entangledLanes;
  if (entangledLanes !== NoLanes) {
    const entanglements = root.entanglements;
    let lanes = nextLanes & entangledLanes;
    while (lanes > 0) {
      const index = pickArbitraryLaneIndex(lanes);
      const lane = 1 << index;

      nextLanes |= entanglements[index];

      lanes &= ~lane;
    }
  }

  return nextLanes;
}
// 获取getEqualOrHigherPriorityLanes 获取更高的lanes, 左移动,并减去1, 
// 即即包含当前优先级及以下所有的
function getEqualOrHigherPriorityLanes(lanes: Lanes | Lane): Lanes {
  return (getLowestPriorityLane(lanes) << 1) - 1;
}

// 返回最高的return_highestLanePriority
export function returnNextLanesPriority() {
  // return_highestLanePriority 返回最高下一个lan 的优先级
  return return_highestLanePriority;
}

// cancelCallback函数定义(6)

// 取消回调函数node
// src/react/packages/react-reconciler/src/SchedulerWithReactIntegration.old.js
// 逻辑: 取消callbackNode
export function cancelCallback(callbackNode: mixed) {
 // 非fakeCallbackNode, 当callbackNode 的 优先级为SyncLanePriority ,
// callbackNode 才会等于fakeCallbackNode, 也就是SyncLanePriority 无法取消
 if (callbackNode !== fakeCallbackNode) {
     Scheduler_cancelCallback(callbackNode);
  }
}
const {
  unstable_cancelCallback: Scheduler_cancelCallback,
} = Scheduler;

// 取消callback 函数
// src/react/packages/scheduler/src/Scheduler.js
function unstable_cancelCallback(task) {
// 可忽略
  if (enableProfiling) {
    if (task.isQueued) {
      const currentTime = getCurrentTime();
      markTaskCanceled(task, currentTime);
      task.isQueued = false;
    }
  }
  // callback 取消
  task.callback = null; // 清空taskNode.callback 时 ,请回回调函数

}

// scheduleSyncCallback 函数(7)

//  调度同步回调
// url : src/react/packages/react-reconciler/src/SchedulerWithReactIntegration.old.js
// 逻辑: 将callbackNode 放入syncQueue,如没有启动,直接Scheduler_scheduleCallback 调度,
// 已经开始,直接压入, 返回fakeCallbackNode
export function scheduleSyncCallback(callback: SchedulerCallback) {//
  // 节点
  // Push this callback into an internal queue. We'll flush these either in
  // the next tick, or earlier if something calls `flushSyncCallbackQueue`.
  // 同步队列为空
  if (syncQueue === null) {
    // 为空,添加
    syncQueue = [callback];
    // Flush the queue in the next tick, at the earliest.
    // 立即执行queue 回调的节点
    immediateQueueCallbackNode = Scheduler_scheduleCallback(
      Scheduler_ImmediatePriority,  // ImmediatePriority : 1
      flushSyncCallbackQueueImpl,
    );
  } else {
    // Push onto existing queue. Don't need to schedule a callback because
    // we already scheduled one when we created the queue.
    // 已经存在, 压入即可,不需要调度, 因为正在调度
    syncQueue.push(callback);
  }
  // 返回
  return fakeCallbackNode;
}
//  newCallbackNode  对应为fakeCallbackNode ,暂时这样,回调的节点都存入syncQueue
// newCallbackNode = scheduleSyncCallback(
 //     performSyncWorkOnRoot.bind(null, root),  // 方法
   //  );
//  syncQueue 中存入的元素为 performSyncWorkOnRoot

// Scheduler_scheduleCallback 函数定义(8)

const {
    unstable_scheduleCallback: Scheduler_scheduleCallback,
} = Scheduler;
// priorityLevel 优先级  , 回调函数  options  配置参数
// url: src/react/packages/scheduler/src/Scheduler.js
// 逻辑: 根据option 生成startTime, 根据priorityLevel,生成expirationTime
// 生成newTask ,根据是否过期,分别压入taskQueue或timerQueue,已过期,requestHostCallback
// 未过期requestHostTimeout
// priorityLevel 优先级  , 回调函数  options  配置参数
function unstable_scheduleCallback(priorityLevel, callback, options) {
 //  priorityLevel:  Scheduler_ImmediatePriority : 1
  //SyncLanePriority, callback:  flushSyncCallbackQueueImpl  //priorityLevel: 1
  // SyncBatchedLanePriority, callback: performSyncWorkOnRoot  // priorityLevel: 1
  // 异步  cacllback:  performConcurrentWorkOnRoot // priorityLevel: 计算
  //  options: null
  var currentTime = getCurrentTime();  // 当前时间

  var startTime;
  if (typeof options === 'object' && options !== null) {
    // 延迟时间
    var delay = options.delay;
    if (typeof delay === 'number' && delay > 0) {
      // 开始时间存在
      startTime = currentTime + delay;
    } else {
      // 不存在
      startTime = currentTime;  // 同步的调用
    }
  } else {
    // 不存在, 同步
    startTime = currentTime;
  }

  var timeout;
  // 优先级
  switch (priorityLevel) {
    case ImmediatePriority:
      timeout = IMMEDIATE_PRIORITY_TIMEOUT;   // 同步 -1/
      break;
    case UserBlockingPriority:
      timeout = USER_BLOCKING_PRIORITY_TIMEOUT; // 250
      break;
    case IdlePriority:
      timeout = IDLE_PRIORITY_TIMEOUT; // 1073741823
      break;
    case LowPriority:
      timeout = LOW_PRIORITY_TIMEOUT; // 10000
      break;
    case NormalPriority:
    default:
      timeout = NORMAL_PRIORITY_TIMEOUT; // 5000
      break;
  }
  // 过期时间
  var expirationTime = startTime + timeout;  // startTime -1
  // 新的任务
  var newTask = {
    id: taskIdCounter++,  // 当前的作用域变量  id, 逐步变大 
    callback,  //  回调函数 flushSyncCallbackQueueImpl
    priorityLevel,  // 优先级 同步的为1 
    startTime,  // 开始时间
    expirationTime,  // 过期时间
    sortIndex: -1,
  };
  //  不处理
  if (enableProfiling) {
    newTask.isQueued = false;
  }
  // 过期时间比当前时间大
  if (startTime > currentTime) {
    // This is a delayed task.
    newTask.sortIndex = startTime; //currentTime
    // timerQueue 队列: []
    push(timerQueue, newTask); // 未过期压入timerQueue, 存入数组
// 并确定timerQueue 的优先级
    // newTask 新建的任务, taskQueue 为空, timerQueue 只有刚存入的节点时
    // 存入的newTask 优先级最高
    if (peek(taskQueue) === null && newTask === peek(timerQueue)) {
      // All tasks are delayed, and this is the task with the earliest delay.
      if (isHostTimeoutScheduled) { // 已经有任务在执行
        // Cancel an existing timeout.
        cancelHostTimeout(); // 取消当前的任务
      } else {
        isHostTimeoutScheduled = true;
      }
      // Schedule a timeout.
      requestHostTimeout(handleTimeout, startTime - currentTime); // // 时间间隔
    }
  } else {
    // 同步的任务, 已经过期,现在同步任务
    newTask.sortIndex = expirationTime; // currentTime -1 
    push(taskQueue, newTask); //过期的 压入taskQueue
    // 不处理
    if (enableProfiling) {
      markTaskStart(newTask, currentTime);
      newTask.isQueued = true;
    }
    // Schedule a host callback, if needed. If we're already performing work,
    // wait until the next time we yield.
    // 等待下一次
    // 是否进行了isHostCallbackScheduled 初始为false
    if (!isHostCallbackScheduled && !isPerformingWork) {
      isHostCallbackScheduled = true;
      requestHostCallback(flushWork); // 进行requestHostCallback
    }
  }

  return newTask;
}
// Tasks are stored on a min heap // 最小堆
var taskQueue = [];
var timerQueue = [];

Heap 构造函数(9)

// 参考: 数据结构:堆(Heap)

// 最小堆
// 最小堆
// url : src/react/packages/scheduler/src/SchedulerMinHeap.js
// 逻辑,最小堆的构造函数定义
type Heap = Array<Node>;
type Node = {|
  id: number,  // 顺序ID
  sortIndex: number,  // 过期时间, 小的放前面
|};
// 节点压入
//  heap : timerQueue, node : newTask
export function push(heap: Heap, node: Node): void {
  const index = heap.length;  // 最后一个,插入的位置
  heap.push(node);  // 最后压入
  siftUp(heap, node, index);  // 节点的 
  /* 
  shiftUp(): 如果一个节点比它的父节点大(最大堆)或者小(最小堆)
  ,那么需要将它同父节点交换位置。这样是这个节点在数组的位置上升。
  
  */
}
// 获取最小的节点,只是查看,是否有最小的节点
export function peek(heap: Heap): Node | null {
  const first = heap[0];
  return first === undefined ? null : first;
}
// 返回最后的一个节点
//:我们取出数组中的最后一个元素,将它放到树的顶部,然后再修复堆属性
export function pop(heap: Heap): Node | null {
  // 第一个
  const first = heap[0];
  // 非空
  if (first !== undefined) {
    const last = heap.pop();
    // 堆中最开始的节点,不是最后的节点,即数组长度不为1 
    if (last !== first) {
      heap[0] = last; // 设置为头部,并移动位置
      siftDown(heap, last, 0);
    }
    return first;
  } else {
    return null;
  }
}
// 新插入的节点的位置移动
function siftUp(heap, node, i) {
  let index = i;
  while (true) {
    // 获取对应的index , 再比较
    const parentIndex = (index - 1) >>> 1;
    const parent = heap[parentIndex];
    // parent, 父节点的比子节点大时,需要更换位置
    if (parent !== undefined && compare(parent, node) > 0) {
      // The parent is larger. Swap positions.
      // 更换位置
      heap[parentIndex] = node;
      heap[index] = parent;
      index = parentIndex;
    } else {
      // The parent is smaller. Exit.
      return;
    }
  }
}
// shiftDown(): 如果一个节点比它的子节点小(最大堆)或者大(最小堆),那么需要将它向下移动。
// 这个操作也称作“堆化(heapify)”。
function siftDown(heap, node, i) {
  let index = i; // 当前的位置
  const length = heap.length; // 堆的长度
  while (index < length) { // 遍历
    const leftIndex = (index + 1) * 2 - 1; // 当前的左子节点的下标
    const left = heap[leftIndex]; // 左节点
    const rightIndex = leftIndex + 1; // 当前的右子节点的下标
    const right = heap[rightIndex]; // 右节点

    // If the left or right node is smaller, swap with the smaller of those.
    // 非空
    if (left !== undefined && compare(left, node) < 0) { // 左节点存在,且比父节点更小
      if (right !== undefined && compare(right, left) < 0) { // 右节点存在,比左节点小
        // 右节点同父节点更换位置
        heap[index] = right;
        heap[rightIndex] = node;
        index = rightIndex;
      } else {
        // 父节点同左节点更换位置
        heap[index] = left;
        heap[leftIndex] = node;
        index = leftIndex;
      }
    } else if (right !== undefined && compare(right, node) < 0) { // 只有右节点比父节点小

      heap[index] = right;
      heap[rightIndex] = node;
      index = rightIndex;
    } else {
      // Neither child is smaller. Exit.
      return;
    }
  }
}
// 比较父子节点的startTime, 过期时间,小的放在前面
// 首先比较sortIndex, 其次比较顺序,前比后小,为false,f
function compare(a, b) {
  // Compare sort index first, then task id.
  const diff = a.sortIndex - b.sortIndex;
  return diff !== 0 ? diff : a.id - b.id;

}

// Tasks are stored on a min heap
var taskQueue = [];
var timerQueue = [];

// cancelHostTimeout 函数定义(10)

// 函数 cancelHostTimeout 定义
// url: src/react/packages/scheduler/src/forks/SchedulerHostConfig.default.js
// 逻辑: 取消taskTimeoutID 任务
cancelHostTimeout = function() {
 clearTimeout(taskTimeoutID);  // 取消taskTimeoutID 对应的任务
 taskTimeoutID = -1;
  };
// 初始值为-1
let taskTimeoutID = -1;

 // 定义执行非同步的任务
  //  ms  时间间隔, callback: handleTimeout  // ms : timer.startTime-currentTime;
  requestHostTimeout = function(callback, ms) {
    taskTimeoutID = setTimeout(() => {
      callback(getCurrentTime());
    }, ms);  // 对应的id 
  };

// performance 接口可以获取到当前页面中与性能相关的信息
// 一个时间计算方式
// getCurrentTime 定义
const hasPerformanceNow =
  typeof performance === 'object' && typeof performance.now === 'function';
// 定义getCurrentTime 时间的函数
if (hasPerformanceNow) {
  const localPerformance = performance;
  getCurrentTime = () => localPerformance.now();
}

// advanceTimers(11)

// 定义advanceTimers
// currentTime getCurrent 传入的时间
// url: src/react/packages/scheduler/src/Scheduler.js
// 逻辑:  循环遍历timerQueue, 判断优先级最高的节点,让callback 清空时
// 将任务,从timerQueue中清除, 当已经过期时,从timerQueue, 移动到taskQueue, 直到无过期任务
function advanceTimers(currentTime) {
  // Check for tasks that are no longer delayed and add them to the queue.
  // 获取timerQueue 优先级最高的节点
  let timer = peek(timerQueue); // 优先级最高的节点
  while (timer !== null) { // 非空
    // 最小的节点已经被取消时, 
    if (timer.callback === null) {  // 节点callback已经取消
      // Timer was cancelled. 
      pop(timerQueue); // 删除最小时间,且回调函数为空
    } else if (timer.startTime <= currentTime) {
      // 时间已经过期
      // Timer fired. Transfer to the task queue.
      pop(timerQueue);// 取出已经过期的第一个任务,且
      timer.sortIndex = timer.expirationTime;
      push(taskQueue, timer); // 将任务转入taskQueue
     // 不分析
      if (enableProfiling) {
        markTaskStart(timer, currentTime);
        timer.isQueued = true;
      }
    } else {
  // 无过期的任务,且无callbak 为空时, 推出循环
      // Remaining timers are pending.
      // 为空时
      return;
    }
    // 再次取更新后的 timerQueue
    timer = peek(timerQueue);
  }
}

// handleTimeout 函数定义(12)

// 未过期的任务的调度
// currentTime  getCurentTime() 返回的时间
// url: src/react/packages/scheduler/src/Scheduler.js
// 逻辑:首先timerQueue中取出callback 为空的优先级最高的节点,并将过期的节点移入taskQueue
// 当isHostCallbackScheduled 没有调度的时候,如taskQueue 非空,继续调度,如taskQueue为空
// 继续执行requestHostTimeout, 
function handleTimeout(currentTime) {
  isHostTimeoutScheduled = false;
  advanceTimers(currentTime); // 当前的时间
  // requestHostCallback 未进行工作时, 
  if (!isHostCallbackScheduled) {
    // timerQueue 过期 压入了任务, 所以可能不为空
    if (peek(taskQueue) !== null) {
      isHostCallbackScheduled = true;
      // 使用requestHostCallback 进行调度
      requestHostCallback(flushWork);
    } else {
      // 获取timerQueue 优先级最高的任务
      const firstTimer = peek(timerQueue);
      // 非空
      if (firstTimer !== null) {
        requestHostTimeout(handleTimeout, firstTimer.startTime - currentTime);
      }
    }
  }
} 
// 备注: isHostTimeoutScheduled 表示是否进行requestHostTimeout 调度 

// requestHostCallback 函数定义(13)

// url: src/react/packages/scheduler/src/forks/SchedulerHostConfig.default.js 
// 逻辑: scheduledHostCallback保存callback , 使用postMessage, 调用performWorkUntilDeadline
const channel = new MessageChannel();
  const port = channel.port2;  // 
  channel.port1.onmessage = performWorkUntilDeadline;
  // 定义了requestHostCallback , window.环境执行
  requestHostCallback = function(callback) {  // flushWork
    // callback: flushWork
    scheduledHostCallback = callback;  // 保存callback
    // scheduledHostCallback: flushWork
    if (!isMessageLoopRunning) {
      isMessageLoopRunning = true;
      port.postMessage(null);
    }
  };
// 取消scheduledHostCallback
cancelHostCallback = function() {
    scheduledHostCallback = null;
  };
/*
我们知道:在浏览器环境中,常见的 macro task 有 setTimeout、MessageChannel、
postMessage、setImmediate。而常见的 micro task 有 MutationObsever 和 Promise.then。
*/
//MessageChannel :  https://www.jianshu.com/p/4f07ef18b5d7
var channel = new MessageChannel();
var port1 = channel.port1;
var port2 = channel.port2;
port1.onmessage = function(event) {
      console.log("port1收到来自port2的数据:" + event.data);
}
port2.onmessage = function(event) {
     console.log("port2收到来自port1的数据:" + event.data);
}

port1.postMessage("发送给port2");
port2.postMessage("发送给port1");

b9c81dd1e8dbacb4b9b63f2e04ed091f.png

// performWorkUntilDeadline 函数定义(14)

// url: src/react/packages/scheduler/src/forks/SchedulerHostConfig.default.js
// 逻辑: scheduledHostCallback 非空, 执行scheduledHostCallback, 执行完判断是否还有返回函数
// 最后清空scheduledHostCallback  和isMessageLoopRunning
const performWorkUntilDeadline = () => {
    // 非空 scheduledHostCallback: 
    if (scheduledHostCallback !== null) { // 非空
      const currentTime = getCurrentTime();
      // Yield after `yieldInterval` ms, regardless of where we are in the vsync
      // cycle. This means there's always time remaining at the beginning of
      // the message event.
      deadline = currentTime + yieldInterval;
      const hasTimeRemaining = true;
      try {
        // 执行scheduledHostCallback 函数: flushWork
        const hasMoreWork = scheduledHostCallback(
          hasTimeRemaining,
          currentTime,
        );
        // 是否有返回的函数
        if (!hasMoreWork) { // 无
          isMessageLoopRunning = false; // 单个执行完毕
          scheduledHostCallback = null;
        } else {
          // If there's more work, schedule the next message event at the end
          // of the preceding one.
// 有返回的函数
          port.postMessage(null);  // 继续执行
        }
      } catch (error) {
        // If a scheduler task throws, exit the current browser task so the
        // error can be observed.
        // 报错
        port.postMessage(null);
        throw error;
      }
    } else {
      // scheduledHostCallback: 被清空
      isMessageLoopRunning = false;
    }
    // Yielding to the browser will give it a chance to paint, so we can
    // reset this.
    needsPaint = false;
  };

// flushWork 函数定义(15)

// 定义flushWork 
// hasTimeRemaining : 是否有时间剩余
// initialTime 初始的时间
// url: src/react/packages/scheduler/src/Scheduler.js
// 逻辑: 如有 isHostTimeoutScheduled 执行,取消, 执行workLoop
function flushWork(hasTimeRemaining, initialTime) {
  // 不处理
  if (enableProfiling) {
    markSchedulerUnsuspended(initialTime);
  }

  // We'll need a host callback the next time work is scheduled.
  // 设置 isHostCallbackScheduled :
  // 已经开始 isHostCallbackScheduled
  isHostCallbackScheduled = false;
  /// 现在正在进行isHostTimeoutScheduled 调度
  if (isHostTimeoutScheduled) {
    // We scheduled a timeout but it's no longer needed. Cancel it.
    isHostTimeoutScheduled = false;
    // 取消
    cancelHostTimeout();
  }
  // 执行isPerformingWork 
  isPerformingWork = true;
  // 当前优先级
  const previousPriorityLevel = currentPriorityLevel;
  try {
    // enableProfiling  // 不处理
    if (enableProfiling) {
      try {
        // 执行workLoop 
        return workLoop(hasTimeRemaining, initialTime);
      } catch (error) {
        if (currentTask !== null) {
          const currentTime = getCurrentTime();
          markTaskErrored(currentTask, currentTime);
          currentTask.isQueued = false;
        }
        throw error;
      }
    } else {
      // No catch in prod code path.
      // 执行wookLoop
      return workLoop(hasTimeRemaining, initialTime);
    }
  } finally {
    currentTask = null;
    // 设置为原来的优先级
    currentPriorityLevel = previousPriorityLevel;
    // isPerformingWork结束
    isPerformingWork = false;
    // 不处理
    if (enableProfiling) {
      const currentTime = getCurrentTime();
      markSchedulerSuspended(currentTime);
    }
  }
}

// workLoop 函数定义(16)

// 执行workLoop 
// 执行workLoop 
// url : src/react/packages/scheduler/src/Scheduler.js
function workLoop(hasTimeRemaining, initialTime) {
  let currentTime = initialTime;
  advanceTimers(currentTime); // 将timerQueue 更新
  currentTask = peek(taskQueue); // 获取最高优先级的callbacknode
// 在执行调度工作循环和计算工作循环时,执行每一个工作中Fiber。
// 但是,有一个条件是每隔5毫秒,会跳出工作循环,
//  export const enableSchedulerDebugging = false;   恒定false
// var isSchedulerPaused = false; 初始为false 
// isSchedulerPaused 调度暂停?
  while (
    currentTask !== null &&
    !(enableSchedulerDebugging && isSchedulerPaused)
  ) {
    // 当前的 currentTask 没有过期
       // hasTimeRemaining:  flushWork 调用时为true
// shouldYieldToHost 总时间5ms, 执行任务, 不足,跳出循环
    if (
      currentTask.expirationTime > currentTime &&  // 未过期的任务
      (!hasTimeRemaining || shouldYieldToHost())  // 
    ) {
// 任务未过期,并且当前调度的deadline到了,将任务放到下次调度周期进行; shouldYieldToHost 
      // hasTimeRemaining  有剩余时间
      // 当前的任务没有过期,且没有剩余时间
      // shouldYieldToHost(): getCurrentTime() >= deadline;  // 当前时间片不足,
      // This currentTask hasn't expired, and we've reached the deadline.
      break;
    }
    // 回调函数
    const callback = currentTask.callback; // 回调函数
   // callback:
    //  SyncLanePriority: flushSyncCallbackQueueImpl
    // SyncBatchedLanePriority:  performSyncWorkOnRoot
    // 异步: performConcurrentWorkOnRoot
    if (typeof callback === 'function') { // wei hanshu 
      currentTask.callback = null; // 首先清空
      currentPriorityLevel = currentTask.priorityLevel; // 优先级
//   // 计算当前任务是否已经超时
      const didUserCallbackTimeout = currentTask.expirationTime <= currentTime; // 是否过期
      // 执行当前currentTask, 还是currentTime
      // if (enableProfiling) { 忽略
      markTaskRun(currentTask, currentTime);
  // [Q]: 执行callback,比如前面render流程分析到的 performConcurrentWorkOnRoot
      const continuationCallback = callback(didUserCallbackTimeout); // 执行callback
// callback:
    //  SyncLanePriority: flushSyncCallbackQueueImpl
    // SyncBatchedLanePriority:  performSyncWorkOnRoot
    // 异步: performConcurrentWorkOnRoot
      currentTime = getCurrentTime();
      // 返回的节点仍然是函数
      if (typeof continuationCallback === 'function') {
        // 将continuationCallback 保存, 继续执行
        currentTask.callback = continuationCallback;
        // 忽略
        markTaskYield(currentTask, currentTime);
      } else {
        // 当返回的任务,不是返回一个函数时
        // 忽略
        if (enableProfiling) {
          markTaskCompleted(currentTask, currentTime);
          currentTask.isQueued = false;
        }
        // 当前的任务, 
        if (currentTask === peek(taskQueue)) {
          //  执行完毕, 删除currentTask
          pop(taskQueue);
        }
      }
      advanceTimers(currentTime); // 更新taskQueue
    } else {
      // 不是函数, 删除taskQueue, 并更新最小堆
// 任务被取消了,弹出任务
      // 回顾下ensureRootIsScheduled 中调用 cancelCallback 的情况
      pop(taskQueue); // 任
    }
    currentTask = peek(taskQueue);  // 返回最高的优先级任务
  }
  // Return whether there's additional work
  // currentTask 是否全部清空
// performWorkUntilDeadline 中判断 hasMoreWork 的逻辑就是这里啦!
  if (currentTask !== null) {
    // 不是
    return true;
  } else {
    // 是否timerQueue
    const firstTimer = peek(timerQueue);
    // 非空
  // [Q]:检测延迟队列中的任务是不是过期
    if (firstTimer !== null) {
      requestHostTimeout(handleTimeout, firstTimer.startTime - currentTime);
    }
    return false;
  }
}

// shouldYieldToHost 函数定义(17)

//  url:  src/react/packages/scheduler/src/forks/SchedulerHostConfig.default.js
// 逻辑: 当前的时间是否超过currentTime + yieldInterval
 shouldYieldToHost = function() {
 // 当前的时间是否 大于deadline
      return getCurrentTime() >= deadline; // 当前时间是否大于deadline
    };
// 定义
   let deadline = 0;
    const performWorkUntilDeadline = () => {
   deadline = currentTime + yieldInterval;  // 修改
}
// 标示markTaskRun 正在执行执行
// url src/react/packages/scheduler/src/SchedulerProfiling.js
export function markTaskRun(
  task: {
    id: number,
    priorityLevel: PriorityLevel,
    ...
  },
  ms: number,
) {
  // 不处理, 可以忽略
  if (enableProfiling) {
    runIdCounter++;

    profilingState[PRIORITY] = task.priorityLevel;
    profilingState[CURRENT_TASK_ID] = task.id;
    profilingState[CURRENT_RUN_ID] = runIdCounter;

    if (eventLog !== null) {
      logEvent([TaskRunEvent, ms * 1000, task.id, runIdCounter]);
    }
  }
}
// 猜测标示任务结束
export function markTaskYield(task: {id: number, ...}, ms: number) {
  // 不处理
  if (enableProfiling) {
    profilingState[PRIORITY] = NoPriority;
    profilingState[CURRENT_TASK_ID] = 0;
    profilingState[CURRENT_RUN_ID] = 0;

    if (eventLog !== null) {
      logEvent([TaskYieldEvent, ms * 1000, task.id, runIdCounter]);
    }
  }
}

// 默认是5
// 强制更新yieldInterval 函数
  forceFrameRate = function(fps) {
    if (fps < 0 || fps > 125) {
      // Using console['error'] to evade Babel and ESLint
      console['error'](
        'forceFrameRate takes a positive int between 0 and 125, ' +
          'forcing frame rates higher than 125 fps is not supported',
      );
      return;
    }
    if (fps > 0) {
      yieldInterval = Math.floor(1000 / fps);
    } else {
      // reset the framerate
      yieldInterval = 5;
    }
  };

// scheduleCallback 函数定义(18)

// url:src/react/packages/react-reconciler/src/SchedulerWithReactIntegration.old.js
// 逻辑: 根据传入的优先级调用Scheduler_scheduleCallback, 与performSyncWork 一致
export function scheduleCallback(
  reactPriorityLevel: ReactPriorityLevel,  // 优先级的层次
  callback: SchedulerCallback, // 回调函数
  options: SchedulerCallbackOptions | void | null,  // 配置项
) {
  // 回调函数
  const priorityLevel = reactPriorityToSchedulerPriority(reactPriorityLevel);
  return Scheduler_scheduleCallback(priorityLevel, callback, options);
}

// 将 react 优先级转换为 调度优先级
// url: src/react/packages/react-reconciler/src/SchedulerWithReactIntegration.old.js
function reactPriorityToSchedulerPriority(reactPriorityLevel) {
  switch (reactPriorityLevel) {
    case ImmediatePriority: // 99
      return Scheduler_ImmediatePriority;  // 1
    case UserBlockingPriority: // 98
      return Scheduler_UserBlockingPriority; // 2
    case NormalPriority: // 97
      return Scheduler_NormalPriority; // 3
    case LowPriority: // 96
      return Scheduler_LowPriority; // 4
    case IdlePriority: // 95
      return Scheduler_IdlePriority; // 5
    default:
      invariant(false, 'Unknown priority level.');
  }
}
// 从而SyncLanePriority 与

// flushSyncCallbackQueueImpl 函数定义(19)

// 清空同步任务队列
// 清空同步任务队列
// url: src/react/packages/react-reconciler/src/SchedulerWithReactIntegration.old.js
//逻辑: 清空syncQueue
function flushSyncCallbackQueueImpl() {
  // syncQueue 非空  isFlushingSyncQueue 为ffalse 
  // isFlushingSyncQueue 同步
  if (!isFlushingSyncQueue && syncQueue !== null) {
    // Prevent re-entrancy.
    isFlushingSyncQueue = true;
    let i = 0;
    //  export const decoupleUpdatePriorityFromScheduler = false;
    // 不处理
    if (decoupleUpdatePriorityFromScheduler) {
      const previousLanePriority = getCurrentUpdateLanePriority();
      try {
        // 是同步
        const isSync = true;
        const queue = syncQueue;
        setCurrentUpdateLanePriority(SyncLanePriority);
        runWithPriority(ImmediatePriority, () => {
          for (; i < queue.length; i++) {
            let callback = queue[i];
            do {
              // 执行同步的任务
              callback = callback(isSync);
            } while (callback !== null);
          }
        });
        // 执行完成清空
        syncQueue = null;
      } catch (error) {
        // If something throws, leave the remaining callbacks on the queue.
        // 同步任务执行,报错,跳过该人人
        if (syncQueue !== null) {
          syncQueue = syncQueue.slice(i + 1);
        }
        // Resume flushing in the next tick
        // 在下一个执行单元恢复执行
        Scheduler_scheduleCallback(
          Scheduler_ImmediatePriority,  // 以最高优先级来清空队列里的任务
          flushSyncCallbackQueue,
        );
        throw error;
      } finally {
        setCurrentUpdateLanePriority(previousLanePriority);
        isFlushingSyncQueue = false;
      }
    } else {
// 真正执行
      try {
         // 是同步
        const isSync = true;
        const queue = syncQueue;  // 同步队列
// ImmediatePriority: 99
        runWithPriority(ImmediatePriority, () => {   // 以最高优先级来清空队列里的任务
          for (; i < queue.length; i++) {
            //第i的任务
            let callback = queue[i];
            do {
                 // 执行同步的任务, 全部清除
              callback = callback(isSync);  // callback: perormSyncWorkOn
            } while (callback !== null);  // 执行完没有报错,返回null
          }
        });
        syncQueue = null;  // 清空
      } catch (error) {
        // If something throws, leave the remaining callbacks on the queue.
          // 移除错误的任务
        if (syncQueue !== null) {
          // 报错时, 跳过这一步
           // 在下一个执行单元恢复执行
          syncQueue = syncQueue.slice(i + 1);
        }
        // Resume flushing in the next tick
        // 下一个tick继续执行
        Scheduler_scheduleCallback(
          Scheduler_ImmediatePriority,
          flushSyncCallbackQueue,
        );
        throw error;
      } finally {
        isFlushingSyncQueue = false;  // 设置原来的值
      }
    }
  }
}

// performConcurrentWorkOnRoot 函数定义(20)

// url: src/react/packages/react-reconciler/src/ReactFiberWorkLoop.old.js
// 逻辑: 暂不, 先其他流程
// This is the entry point for every concurrent task, i.e. anything that
// goes through Scheduler.
function performConcurrentWorkOnRoot(root) {
  // Since we know we're in a React event, we can clear the current
  // event time. The next update will compute a new event time.
  currentEventTime = NoTimestamp;
  currentEventWipLanes = NoLanes;
  currentEventPendingLanes = NoLanes;

  // Flush any pending passive effects before deciding which lanes to work on,
  // in case they schedule additional work.
  const originalCallbackNode = root.callbackNode;
  const didFlushPassiveEffects = flushPassiveEffects();
  if (didFlushPassiveEffects) {
    // Something in the passive effect phase may have canceled the current task.
    // Check if the task node for this root was changed.
    if (root.callbackNode !== originalCallbackNode) {
      // The current task was canceled. Exit. We don't need to call
      // `ensureRootIsScheduled` because the check above implies either that
      // there's a new task, or that there's no remaining work on this root.
      return null;
    } else {
      // Current task was not canceled. Continue.
    }
  }

  // Determine the next expiration time to work on, using the fields stored
  // on the root.
  let lanes = getNextLanes(
    root,
    root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes,
  );
  if (lanes === NoLanes) {
    // Defensive coding. This is never expected to happen.
    return null;
  }

  let exitStatus = renderRootConcurrent(root, lanes);

  if (
    includesSomeLane(
      workInProgressRootIncludedLanes,
      workInProgressRootUpdatedLanes,
    )
  ) {
    // The render included lanes that were updated during the render phase.
    // For example, when unhiding a hidden tree, we include all the lanes
    // that were previously skipped when the tree was hidden. That set of
    // lanes is a superset of the lanes we started rendering with.
    //
    // So we'll throw out the current work and restart.
    prepareFreshStack(root, NoLanes);
  } else if (exitStatus !== RootIncomplete) {
    if (exitStatus === RootErrored) {
      executionContext |= RetryAfterError;

      // If an error occurred during hydration,
      // discard server response and fall back to client side render.
      if (root.hydrate) {
        root.hydrate = false;
        clearContainer(root.containerInfo);
      }

      // If something threw an error, try rendering one more time. We'll render
      // synchronously to block concurrent data mutations, and we'll includes
      // all pending updates are included. If it still fails after the second
      // attempt, we'll give up and commit the resulting tree.
      lanes = getLanesToRetrySynchronouslyOnError(root);
      if (lanes !== NoLanes) {
        exitStatus = renderRootSync(root, lanes);
      }
    }

    if (exitStatus === RootFatalErrored) {
      const fatalError = workInProgressRootFatalError;
      prepareFreshStack(root, NoLanes);
      markRootSuspended(root, lanes);
      ensureRootIsScheduled(root, now());
      throw fatalError;
    }

    // We now have a consistent tree. The next step is either to commit it,
    // or, if something suspended, wait to commit it after a timeout.
    const finishedWork: Fiber = (root.current.alternate: any);
    root.finishedWork = finishedWork;
    root.finishedLanes = lanes;
    finishConcurrentRender(root, exitStatus, lanes);
  }

  ensureRootIsScheduled(root, now());
  if (root.callbackNode === originalCallbackNode) {
    // The task node scheduled for this root is the same one that's
    // currently executed. Need to return a continuation.
    return performConcurrentWorkOnRoot.bind(null, root);
  }
  return null;
}

// runWithPriority 函数定义(21)

// 定义runWithPriority 函数
// url: src/react/packages/react-reconciler/src/SchedulerWithReactIntegration.old.js
// 逻辑: 以特定优先级执行fn
export function runWithPriority<T>(
  reactPriorityLevel: ReactPriorityLevel,
  fn: () => T,
): T {
  // priorityLevel: 1
  const priorityLevel = reactPriorityToSchedulerPriority(reactPriorityLevel);
  return Scheduler_runWithPriority(priorityLevel, fn);
  // priorityLevel: 1, fn: 匿名函数
}

const {
  unstable_runWithPriority: Scheduler_runWithPriority,
} = Scheduler;

// 以特定的优先级执行eventHandler
// url: src/react/packages/scheduler/src/Scheduler.js
// 逻辑: 以当前传入的执行eventHandler 函数
function unstable_runWithPriority(priorityLevel, eventHandler) {
  switch (priorityLevel) {
    case ImmediatePriority:
    case UserBlockingPriority:
    case NormalPriority:
    case LowPriority:
    case IdlePriority:
      break;
    default:
      priorityLevel = NormalPriority;
  }
  // 保存当前优先级
  var previousPriorityLevel = currentPriorityLevel;
  // 更新为传入的优先级
  currentPriorityLevel = priorityLevel;

  try {
    // 执行eventHandler 函数  , 清空sync的匿名函数
    return eventHandler();
  } finally {
    // 还原
    currentPriorityLevel = previousPriorityLevel;
  }
}

图片(1)

93adcb59e7f8eb708f0b5b76a3d5d499.png
当进行scheduleUpdateOnFiber 更新时, 当更新为同步,且context为非render 且非commit, 且为非批量更新时,执行performSyncWorkOnRoot, 其余状态执行ensureRootIsScheduled

10a802f613aa82e20f72d6b5462a7aad.png

图2

8bb72ae6c19b6b37a5b456c6224d7ad7.png

图3

总结: (1)scheduleUpdateOnFiber开始, 当lane 为同步, 非批量,且处于非render或非commit, 将通过performSyncWorkOnRoot 进行调度。其他情况通过ensureRootIsScheduled 进行调度,同步情况,调度完毕,且无上下文,执行flushSyncCallbackQueue。

(2)ensureRootIsScheduled: 根据pendingLanes, 更新expiredLanes, 获取callbackNode和对应的优先级, 计算新的callbackPriority ,进行比较, 相同则结束流程, 不同,取消callbackNode。根据newCallbackPriority 调度新的callback, SyncLanePriority时, scheduleSyncCallback(performSyncWorkOnRoot)产生, SyncBatchedLanePriority 时, scheduleCallback(performSyncWorkOnRoot),, 异步时, scheduleCallback(performConcurrentWorkOnRoot), priority通过函数产生。

(3)scheduleSyncCallback: 当syncQueue 为空, 保存为一个元素数组,元素为performSyncWorkOnRoot, 且通过Scheduler_scheduleCallback 调度开始。不为空,调度已经开始,直接添加入syncQueue。Scheduler_scheduleCallback 的priority 为1, SyncBatchedLanePriority也为1。优先级为SyncLanePriority 时,newCallbackNode 为fakeCallbackNode。immediateQueueCallbackNode 为Scheduler_scheduleCallback 调用返回。

(4)优先级为SyncBatchedLanePriority 时, priority 为1 ,Scheduler_scheduleCallback 进行调度, 与SyncLanePriority 优先级一致,只是相同点, 不同: 没有处理syncQueue 和设置immediateQueueCallbackNode, callback为performSyncWorkOnRoot, 而SyncLanePriority 的callback 为flushSyncCallbackQueueImpl。

(5)优先级为异步的情况, priority 通过函数获取, callback为performConcurrentWorkOnRoot。 暂时不分析。

(6)unstable_scheduleCallback : 通过options , priorityLevel和currentTime 计算出过期时间。优先级越高,过期时间越小, 由expirationTime和callback,生成newTask。根据expirationTime是过期,压入taskQueue, 未进行requestHostCallback时, 调用requestHostCallback(flushWork)。当未过期时, 当无taskQueue,且newTask为timerQueue时, 当timeoutScheduled调度时, 取消调度,以最新的newTask 进行调度。

(7) requestHostTimeout : 开始执行isHostTimeoutScheduled时,isHostTimeoutScheduled 为 true; 使用setTimeout ,在expirationtTime-currentTime, 执行handleTimeout, sHostTimeoutScheduled 为 false, 回调函数的逻辑, 将timeQueue中callback的节点删除,已经过期的callback转入taskQueue, 且在requestHostCallback 未工作时,判断taskQueue 是否有任务,有任务,则开始requestHostCallback, 否则取出timerQueue中优先级最高的节点,继续requestHostTimeout。从而,整体逻辑,单个同步,批量同步存入taskQueue, 异步为过期的存入timeQueue, requestHostTimeout 不停调度timeQueue 优先级最高的节点, 从而将callback移入taskQueue, 并开始requestHostCallback。

(8)requestHostCallback 将scheduledHostCallback 保存callback : flushwork, 使用MessageChannel 传递调用, 异步传递,从而执行函数performWorkUntilDeadline。

(9)performWorkUntilDeadline 获取当前时间和deadline , 执行scheduledHostCallback ,即flushwork。flushWork调用时, isHostCallbackScheduled 更改为false, 如果正在执行requestHostTimeout, 则取消requestHostTimeout, 执行workLoop, 并将结果返回, 执行workLoop时, 设置isPerformingWork为true, 结束时,设置isPerformingWork 为false。

(10)workLoop: 将timerQueue 更新, 从taskQueue 取出最高优先级的callback,isSchedulerPaused 为false时, isSchedulerPaused 调度暂停开关, 当前task没有过期, 且时间片不足(5ms已用完), 跳出循环, 当有过期任务,或者仍有时间片时,执行callbackNode中的callback,并传入是否过期的boolean, 执行callback 后,仍返回函数,将函数保存为callbackNode的callback,不是返回函数,则清除当前callbackNode,并更新timerQueue。当跳出循环后, (1)currentTask有值, 这个值来源于timerQueue的更新。则返回true, 赋值给performWorkUntilDeadline的hasMoreWork, 通过postMessage 传递给performWorkUntilDeadline, 将在下一个5ms执行flushwork。(2)currentTask 为空,判断timerQueue是否为空, 不为空,开启requestHostTimeout 调度。

(11) shouldYieldToHost: 设置一个时间间隔, 间隔为5ms。

(12) flushSyncCallbackQueueImpl: runWithPriority执行包裹清空syncQueue的匿名函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值