requestWork的最后,调用了performSyncWork(同步任务)和scheduleCallbackWithExpirationTime,其中,scheduleCallbackWithExpirationTime最后调用的函数是performAsyncWork(异步任务);
performSyncWork
typescript
function performSyncWork() {
performWork(Sync, false);
}performAsyncWork
typescript
function performAsyncWork() {
try {
if (!shouldYieldToRenderer()) {
// 如果进入到此回调
// 说明当前执行的回调已经超时,也就是说最近的更新过期了
if (firstScheduledRoot !== null) {
recomputeCurrentRendererTime();
let root: FiberRoot = firstScheduledRoot;
do {
didExpireAtExpirationTime(root, currentRendererTime);
root = (root.nextScheduledRoot: any);
} while (root !== firstScheduledRoot);
}
}
performWork(NoWork, true);
} finally {
didYield = false;
}
}performSyncWork和performAsyncWork最后调用的其实都是performWork,唯一的区别就在第二个参数isYieldy的区别上,isYieldy代表的是当前任务可中断
performWork
typescript
function performWork(minExpirationTime: ExpirationTime, isYieldy: boolean) {
// 找到优先级更高的那个FiberRoot和他的时间
// 赋值给 nextFlushedRoot 和 nextFlushedExpirationTime
findHighestPriorityRoot();
// 判断isYieldy 为异步任务会走到这里来
if (isYieldy) {
// 异步任务,重新计算currentSchedulerTime
recomputeCurrentRendererTime();
currentSchedulerTime = currentRendererTime;
while (
nextFlushedRoot !== null &&
nextFlushedExpirationTime !== NoWork &&
minExpirationTime <= nextFlushedExpirationTime &&
!(didYield && currentRendererTime > nextFlushedExpirationTime)
) {
// 这里的条件的意思是
// 下一个待执行的FiberRoot不是null 并且 nextFlushedExpirationTime 不等于NoWork
// minExpirationTime小于或等于nextFlushedExpirationTime;一般情况下两者是相等的
// !(didYield && currentRendererTime > nextFlushedExpirationTime)
// 这个条件 就是说,didYield 为false 或者
// currentRendererTime > nextFlushedExpirationTime 不成立
// 也就是 时间片还有时间,但是当前任务已经超时了 会进入此判断
// 还有就是一贞的时间执行完了 当前任务没超时 会进入次判断
// 当前渲染时间是否大于nextFlushedExpirationTime,也就是判断任务是否已经超时了了,
// 如果超时了,根据下面调用performWorkOnRoot的参数中
// 有一个currentRendererTime > nextFlushedExpirationTime,
// 也就是这种情况下为true,代表的意思是同步执行任务不再判断是否时间片到期。
performWorkOnRoot(
nextFlushedRoot,
nextFlushedExpirationTime,
currentRendererTime > nextFlushedExpirationTime,
);
findHighestPriorityRoot();
recomputeCurrentRendererTime();
currentSchedulerTime = currentRendererTime;
}
} else {
// 同步的情况
while (
nextFlushedRoot !== null &&
nextFlushedExpirationTime !== NoWork &&
minExpirationTime <= nextFlushedExpirationTime
) {
// while循环的意思是什么呢?
// 下一个待执行的FiberRoot不是null 并且 nextFlushedExpirationTime不是NoWork
// 并且 minExpiration 小于或等于 nextFlushedExpirationTime
// 在同步任务的时候 nextFlushedExpirationTime 就是等于minExpiration 等于NoWork
// 只有当FiberRoot上的任务都执行完了 就会跳出while循环
performWorkOnRoot(nextFlushedRoot, nextFlushedExpirationTime, false);
findHighestPriorityRoot();
}
}
if (isYieldy) {
callbackExpirationTime = NoWork;
callbackID = null;
}
if (nextFlushedExpirationTime !== NoWork) {
scheduleCallbackWithExpirationTime(
((nextFlushedRoot: any): FiberRoot),
nextFlushedExpirationTime,
);
}
}performWorkOnRoot
说明
这里的root指的是FiberRoot, 也就是说,react的渲染是从FiberRoot开始的
typescript
function performWorkOnRoot(
root: FiberRoot,
expirationTime: ExpirationTime,
isYieldy: boolean,
) {
isRendering = true;
if (!isYieldy) {
// 同步任务和异步的超时任务会走到这
let finishedWork = root.finishedWork;
if (finishedWork !== null) {
// 如果存在 说明render过程完成 可以commit了
completeRoot(root, finishedWork, expirationTime);
} else {
root.finishedWork = null;
// 在任务被挂起的时候通过setTimeout设置的返回内容,
// 用来下一次如果有新的任务挂起时清理还没触发的timeout
const timeoutHandle = root.timeoutHandle;
if (timeoutHandle !== noTimeout) {
root.timeoutHandle = noTimeout;
cancelTimeout(timeoutHandle);
}
renderRoot(root, isYieldy);
finishedWork = root.finishedWork;
if (finishedWork !== null) {
completeRoot(root, finishedWork, expirationTime);
}
}
} else {
// 执行异步任务
let finishedWork = root.finishedWork;
if (finishedWork !== null) {
completeRoot(root, finishedWork, expirationTime);
} else {
root.finishedWork = null;
const timeoutHandle = root.timeoutHandle;
if (timeoutHandle !== noTimeout) {
root.timeoutHandle = noTimeout;
cancelTimeout(timeoutHandle);
}
renderRoot(root, isYieldy);
finishedWork = root.finishedWork;
if (finishedWork !== null) {
// 首先检查当前一贞的时间片还有没有时间
// 如果时间不够,就留到下一帧处理,如果时间还有,就执行commit
if (!shouldYieldToRenderer()) {
completeRoot(root, finishedWork, expirationTime);
} else {
root.finishedWork = finishedWork;
}
}
}
}
isRendering = false;
}performWorkOnRoot主要是从FiberRoot节点开始执行,分为2个阶段: