此文中的可能,只是在看源码时的记录笔记,暂时没有解决。
中断的可能
React-recociler中的参数可分为基础的、Mutation(变化)、Persistence(持续;固执;存留)、Hydration(水合作用)。
// 下面标识了中断的可能function stopWorkLoopTimer(interruptedBy, didCompleteRoot) {if (enableUserTimingAPI) {if (!supportsUserTiming) {return;}var warning = null;if (interruptedBy !== null) {if (interruptedBy.tag === HostRoot) {warning = 'A top-level update interrupted the previous render';//@中断可能一} else {var componentName = getComponentName(interruptedBy.type) || 'Unknown';warning = 'An update to ' + componentName+ ' interrupted the previous render';//@中断可能二}} else if (commitCountInCurrentWorkLoop > 1) {warning = 'There were cascading updates';}commitCountInCurrentWorkLoop = 0;var label = didCompleteRoot ?'(React Tree Reconciliation: Completed Root)' : '(React Tree Reconciliation: Yielded)';// Pause any measurements until the next loop.pauseTimers();endMark(label, '(React Tree Reconciliation)', warning);}}
延迟执行
if (finishedWork !== null) {// We've completed the root. Commit it.completeRoot(root, finishedWork, expirationTime);}
在completeRoot 中有一段代码,可阻止当前提交,等待下一次提价的:
function completeRoot(root: FiberRoot, finishedWork: Fiber,expirationTime: ExpirationTime): void {// Check if there's a batch that matches this expiration time.const firstBatch = root.firstBatch;if (firstBatch !== null && firstBatch._expirationTime >= expirationTime) {if (completedBatches === null) {completedBatches = [firstBatch];} else {completedBatches.push(firstBatch);}if (firstBatch._defer) {// 阻止提交// This root is blocked from committing by a batch. Unschedule it until// we receive another update.root.finishedWork = finishedWork;root.expirationTime = NoWork;return;}}// ...commitRoot(root, finishedWork);}
firstBatch._defer 为true,可阻止提交。
firstBatch._defer 为true就阻止本次提交并等待下一次提交。查了查代码,发现 _defer 是在 ReactDOM 源码中packages\react-dom\src\client\ReactDOM.js 中 ReactBatch,代码如下:
function ReactBatch(root: ReactRoot) {const expirationTime = computeUniqueAsyncExpiration();this._expirationTime = expirationTime;//设置的时间this._root = root;this._next = null;this._callbacks = null;this._didComplete = false;this._hasChildren = false;this._children = null;this._defer = true;//初始设置为true}/**此处的重点不在这,省略....代码*/
