1.核心知识点
有deadline区分 date.now()-nextframe(下一个requestAnimation执行的时间搓)
循环渲染root的条件
异步work超过时间片的处理 交回给浏览器执行
2.performAsyncWork performsyncWork performwork
//!找到root链表中最高优先级的root 赋值给nextFlushedRoot和nextFlushedExpirationTimes属性
function findHighestPriorityRoot() {
let highestPriorityWork = NoWork;
let highestPriorityRoot = null;
if (lastScheduledRoot !== null) {
let previousScheduledRoot = lastScheduledRoot;
let root = firstScheduledRoot;
while (root !== null) {//!循环找优先级最高的root
const remainingExpirationTime = root.expirationTime;
if (remainingExpirationTime === NoWork) {//!这个root没有任何跟新 那么删除这个root 下面四个if都是删除root
// This root no longer has work. Remove it from the scheduler.
// TODO: This check is redudant, but Flow is confused by the branch
// below where we set lastScheduledRoot to null, even though we break
// from the loop right after.
invariant(
previousScheduledRoot !== null && lastScheduledRoot !== null,
'Should have a previous and last root. This error is likely ' +
'caused by a bug in React. Please file an issue.',
);
if (root === root.nextScheduledRoot) {//!整个应用只有一个root 且没跟新
// This is the only root in the list.
root.nextScheduledRoot = null;
firstScheduledRoot = lastScheduledRoot = null;
break;
} else if (root === firstScheduledRoot) {//!第一个
// This is the first root in the list.
const next = root.nextScheduledRoot;
firstScheduledRoot = next;
lastScheduledRoot.nextScheduledRoot = next;
root.nextScheduledRoot = null;
} else if (root === lastScheduledRoot) {//!最后一个
// This is the last root in the list.
lastScheduledRoot = previousScheduledRoot;
lastScheduledRoot.nextScheduledRoot = firstScheduledRoot;
root.nextScheduledRoot = null;
break;
} else {//!中间
previousScheduledRoot.nextScheduledRoot = root.nextScheduledRoot;
root.nextScheduledRoot = null;
}
root = previousScheduledRoot.nextScheduledRoot;
} else {
//!这个root有更新
if (
highestPriorityWork === NoWork ||
remainingExpirationTime < highestPriorityWork
) {
// Update the priority, if it's higher
highestPriorityWork = remainingExpirationTime;
highestPriorityRoot = root;
}
if (root === lastScheduledRoot) {
break;
}
if (highestPriorityWork === Sync) {
// Sync is highest priority by definition so
// we can stop searching.
break;
}
previousScheduledRoot = root;
root = root.nextScheduledRoot;
}
}
}
nextFlushedRoot = highestPriorityRoot;
nextFlushedExpirationTime = highestPriorityWork;
}
function performAsyncWork(dl) {//!这个是经过schedule调度回来在空闲时间会执行的函数 dl是dealine 有两个属性 分别是timeremaining 和didtimeout
if (dl.didTimeout) {//!过期
// The callback timed out. That means at least one update has expired.
// Iterate through the root schedule. If they contain expired work, set
// the next render expiration time to the current time. This has the effect
// of flushing all expired work in a single batch, instead of flushing each
// level one at a time.
if (firstScheduledRoot !== null) {
recomputeCurrentRendererTime();//!不管
let root: FiberRoot = firstScheduledRoot;
do {
didExpireAtExpirationTime(root, currentRendererTime);//!标记root节点上的变量 修改一个属性为currentTime
// The root schedule is circular, so this is never null.
root = (root.nextScheduledRoot: any);
} while (root !== firstScheduledRoot);//!遍历root
}
}
performWork(NoWork, dl);
}
function performSyncWork() {
performWork(Sync, null);//!传入sync
}
//!while循环条件 有节点且处于同步/异步状态
function performWork(minExpirationTime: ExpirationTime, dl: Deadline | null) {
deadline = dl;
// Keep working on roots until there's no more work, or until we reach
// the deadline.
findHighestPriorityRoot();//!找到root链表中最高优先级的root 赋值给nextFlushedRoot和nextFlushedExpirationTimes属性
if (deadline !== null) {
recomputeCurrentRendererTime();
currentSchedulerTime = currentRendererTime;
if (enableUserTimingAPI) {
const didExpire = nextFlushedExpirationTime < currentRendererTime;
const timeout = expirationTimeToMs(nextFlushedExpirationTime);
stopRequestCallbackTimer(didExpire, timeout);
}
while (
nextFlushedRoot !== null &&
nextFlushedExpirationTime !== NoWork &&
(minExpirationTime === NoWork || //!minExpirationTime为sync时候 只会执行nextFlushedExpirationTime=sync的更新 及同步更新 minExpirationTime === NoWork是异步更新 所以同步异步在这个或里面都能行
minExpirationTime >= nextFlushedExpirationTime) &&
(!deadlineDidExpire || currentRendererTime >= nextFlushedExpirationTime)//!当前时间大于expirationTime表示任务过期
) {
performWorkOnRoot(//!在root上更新 过期则最后一个值传true 不过期传false
nextFlushedRoot,
nextFlushedExpirationTime,
currentRendererTime >= nextFlushedExpirationTime,
);
findHighestPriorityRoot();//!再找root高优先级的任务 然后下一个循环执行
recomputeCurrentRendererTime();//!重新计算currentTime()
currentSchedulerTime = currentRendererTime;
}
} else {
while (
nextFlushedRoot !== null &&
nextFlushedExpirationTime !== NoWork &&
(minExpirationTime === NoWork || //!minExpirationTime为sync时候 只会执行nextFlushedExpirationTime=sync的更新 及同步更新 minExpirationTime === NoWork是异步更新 所以同步异步在这个或里面都能行
minExpirationTime >= nextFlushedExpirationTime)
) {
performWorkOnRoot(nextFlushedRoot, nextFlushedExpirationTime, true);//!过期直接传true
findHighestPriorityRoot();
}
}
// We're done flushing work. Either we ran out of time in this callback,
// or there's no more work left with sufficient priority.
// If we're inside a callback, set this to false since we just completed it.
if (deadline !== null) {
callbackExpirationTime = NoWork;
callbackID = null;
}
// If there's work left over, schedule a new callback.
if (nextFlushedExpirationTime !== NoWork) {
scheduleCallbackWithExpirationTime(
((nextFlushedRoot: any): FiberRoot),
nextFlushedExpirationTime,
);
}
// Clean-up.
deadline = null;
deadlineDidExpire = false;
finishRendering();
}