You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
functionperformAsyncWork(dl){// didTimeout 为 true 任务过期,立即执行if(dl.didTimeout){if(firstScheduledRoot!==null){// 设置当前渲染时间为当前时间recomputeCurrentRendererTime();
let root: FiberRoot=firstScheduledRoot;do{// 标记 root 节点变量, 如果当前任务过期设置root.newExpirationTimeToWorkOn 为当前时间didExpireAtExpirationTime(root,currentRendererTime);// 找 下一个 rootroot=(root.nextScheduledRoot: any);}while(root!==firstScheduledRoot);}}performWork(NoWork,dl);}functionperformSyncWork(){performWork(Sync,null);}functiondidExpireAtExpirationTime(root: FiberRoot,currentTime: ExpirationTime,): void{constexpirationTime=root.expirationTime;// root 已经过期if(expirationTime!==NoWork&¤tTime>=expirationTime){// The root has expired. Flush all work up to the current time.//root.nextExpirationTimeToWorkOn=currentTime;}}
functionshouldYield(){if(deadlineDidExpire){returntrue;}// deadline.timeRemaining 返回的值表示一帧渲染时间还有剩余, 直接return false, 此时deadlineDidExpire 为falseif(deadline===null||deadline.timeRemaining()>timeHeuristicForUnitOfWork){// Disregard deadline.didTimeout. Only expired work should be flushed// during a timeout. This path is only hit for non-expired work.returnfalse;}deadlineDidExpire=true;returntrue;}
functionperformWork(minExpirationTime: ExpirationTime,dl: Deadline|null){deadline=dl;// Keep working on roots until there's no more work, or until we reach// the deadline.findHighestPriorityRoot();// 异步if(deadline!==null){// 重新计算当前渲染时间recomputeCurrentRendererTime();currentSchedulerTime=currentRendererTime;while(nextFlushedRoot!==null&&nextFlushedExpirationTime!==NoWork&&(minExpirationTime===NoWork||minExpirationTime>=nextFlushedExpirationTime)&&// 还有剩余时间更新 或者 任务已经过期需要强制输出(!deadlineDidExpire||currentRendererTime>=nextFlushedExpirationTime)){performWorkOnRoot(nextFlushedRoot,nextFlushedExpirationTime,// 过期为 true,未过期为 falsecurrentRendererTime>=nextFlushedExpirationTime,);findHighestPriorityRoot();recomputeCurrentRendererTime();currentSchedulerTime=currentRendererTime;}}else{// 同步while(// root 非空nextFlushedRoot!==null&&// root 有更新nextFlushedExpirationTime!==NoWork&&// minExpirationTime 为 Sync,那么就只能是处理 nextFlushedExpirationTime 为Sync的情况,即同步执行的情况(minExpirationTime===NoWork||minExpirationTime>=nextFlushedExpirationTime)){performWorkOnRoot(nextFlushedRoot,nextFlushedExpirationTime,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();}
functionfindHighestPriorityRoot(){lethighestPriorityWork=NoWork;lethighestPriorityRoot=null;// 有 root 的情况if(lastScheduledRoot!==null){letpreviousScheduledRoot=lastScheduledRoot;letroot=firstScheduledRoot;while(root!==null){constremainingExpirationTime=root.expirationTime;// Nowork 表示节点没有更新if(remainingExpirationTime===NoWork){// This root no longer has work. Remove it from the scheduler.// 只有一个 root 的情况if(root===root.nextScheduledRoot){// This is the only root in the list.root.nextScheduledRoot=null;firstScheduledRoot=lastScheduledRoot=null;break;}// ....}else{// root 上有更新if(highestPriorityWork===NoWork||remainingExpirationTime<highestPriorityWork){// Update the priority, if it's higher// 找更新优先级最高的 root 和它对应的 expirationTimehighestPriorityWork=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;}
functionperformWorkOnRoot(root: FiberRoot,expirationTime: ExpirationTime,isExpired: boolean,){isRendering=true;// Check if this is async work or sync/expired work.// 同步任务 或者 过期任务if(deadline===null||isExpired){// Flush work without yielding.// TODO: Non-yieldy work does not necessarily imply expired work. A renderer// may want to perform some work without yielding, but also without// requiring the root to complete (by triggering placeholders).letfinishedWork=root.finishedWork;// 上一次 renderRoot 完,但没有时间 completeRoot 了if(finishedWork!==null){// This root is already complete. We can commit it.completeRoot(root,finishedWork,expirationTime);}else{root.finishedWork=null;// If this root previously suspended, clear its existing timeout, since// we're about to try rendering again.// suspense 功能相关consttimeoutHandle=root.timeoutHandle;if(timeoutHandle!==noTimeout){root.timeoutHandle=noTimeout;// $FlowFixMe Complains noTimeout is not a TimeoutID, despite the check abovecancelTimeout(timeoutHandle);}// 表示这个任务不可中断(同步或过期任务不可中断)constisYieldy=false;// renderRoot 之后赋值 finishedWorkrenderRoot(root,isYieldy,isExpired);finishedWork=root.finishedWork;if(finishedWork!==null){// We've completed the root. Commit it.completeRoot(root,finishedWork,expirationTime);}}}else{// Flush async work.letfinishedWork=root.finishedWork;if(finishedWork!==null){// This root is already complete. We can commit it.completeRoot(root,finishedWork,expirationTime);}else{root.finishedWork=null;// If this root previously suspended, clear its existing timeout, since// we're about to try rendering again.consttimeoutHandle=root.timeoutHandle;if(timeoutHandle!==noTimeout){root.timeoutHandle=noTimeout;// $FlowFixMe Complains noTimeout is not a TimeoutID, despite the check abovecancelTimeout(timeoutHandle);}// 异步任务是可以中断的constisYieldy=true;// renderRoot 之后赋值 finishedWorkrenderRoot(root,isYieldy,isExpired);finishedWork=root.finishedWork;// 可能被中断,被中断 finishedWork 为nullif(finishedWork!==null){// We've completed the root. Check the deadline one more time// before committing.// 还有剩余时间更新则继续 completeRootif(!shouldYield()){// Still time left. Commit the root.completeRoot(root,finishedWork,expirationTime);}else{// 没有时间更新了, 待到下个时间段进入 performWorkOnRoot 判断// There's no time left. Mark this root as complete. We'll come// back and commit it later.root.finishedWork=finishedWork;}}}}isRendering=false;}
The text was updated successfully, but these errors were encountered:
performSyncWork 和 perfromAsyncWork
performWork
minExpirationTime
为NoWork 0
,通过判断dl.didTimeout
是否过期,如果过期则设置root.newExpirationTimeToWorkOn
为当前时间,表示这个任务可以直接执行,不需要判断是否超过帧时间minExpirationTime
为Sync 1
performAsyncWork
performWork
是否有
deadline
的区分异步/同步,用来判断一帧的渲染时间内还有没有时间留给 React 更新的循环渲染 Root 的条件:循环不同 root 和不同优先级任务来更新
超过时间片的处理:deadline 这一帧的时间到了把执行权交回浏览器
shouldYield 方法用来判断一帧渲染时间内是否还有剩余时间留个React更新,改变全局变量
deadlineDidExpire
,为 false 表示还有时间留给React更新findHighestPriorityRoot
nextFlushedRoot
, root对应的expirationTime
赋值给nextFlushedExpirationTime
performWorkonRoot
isRendering
置为true
,执行完后为false
renderRoot
渲染阶段completeRoot
提交(commit)阶段-
finishedWork
是已经完成renderRoot
渲染阶段的任务,只有renderRoot
后才不为null
completeRoot
提交。没有剩余时间则等到下个时间段进入performWorkOnRoot
判断The text was updated successfully, but these errors were encountered: