
// 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");

// 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)


图2

图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的匿名函数。