人工智能设计网站,沈阳网站建设多少钱,浙江手机版建站系统开发,成都私家花园设计公司哪家好不同的 expirationTime 1 #xff09;概述
在React中不仅仅有异步任务大部分情况下都是同步的任务#xff0c;所以会有不同 expirationTime 的存在
2 #xff09;种类
A. Sync 模式#xff0c;优先级最高 任务创建完成之后#xff0c;立马更新到真正的dom里面是一个创建…不同的 expirationTime 1 概述
在React中不仅仅有异步任务大部分情况下都是同步的任务所以会有不同 expirationTime 的存在
2 种类
A. Sync 模式优先级最高 任务创建完成之后立马更新到真正的dom里面是一个创建即更新的流程 B. Async 模式, 异步模式 会有一个调度包含一系列复杂的操作在里面可能会中断所以会有一个计算出来的过期时间过期时间根据异步的两种情况如前文所述 最低优先级的异步最高优先级的异步 C. 指定context
3 ) 源码
在 ReactFiberReconciler.js 中的 updateContainer 中 调用的是 computeExpirationForFiber 它接收两个参数: currentTime: ExpirationTime, fiber: Fiber 这个方法来自于 ReactFiberScheduler.js 文件function computeExpirationForFiber(currentTime: ExpirationTime, fiber: Fiber) {let expirationTime;if (expirationContext ! NoWork) {// An explicit expiration context was set;expirationTime expirationContext;} else if (isWorking) {if (isCommitting) {// Updates that occur during the commit phase should have sync priority// by default.expirationTime Sync;} else {// Updates during the render phase should expire at the same time as// the work that is being rendered.expirationTime nextRenderExpirationTime;}} else {// No explicit expiration context was set, and were not currently// performing work. Calculate a new expiration time.if (fiber.mode ConcurrentMode) {if (isBatchingInteractiveUpdates) {// This is an interactive updateexpirationTime computeInteractiveExpiration(currentTime);} else {// This is an async updateexpirationTime computeAsyncExpiration(currentTime);}// If were in the middle of rendering a tree, do not update at the same// expiration time that is already rendering.if (nextRoot ! null expirationTime nextRenderExpirationTime) {expirationTime 1;}} else {// This is a sync updateexpirationTime Sync;}}if (isBatchingInteractiveUpdates) {// This is an interactive update. Keep track of the lowest pending// interactive expiration time. This allows us to synchronously flush// all interactive updates when needed.if (expirationTime lowestPriorityPendingInteractiveExpirationTime) {lowestPriorityPendingInteractiveExpirationTime expirationTime;}}return expirationTime;
}1 这里有一系列的判断首先是对 expirationContext 的判断 它是 ExpirationTime 类型默认初始化值是 NoWork下面是它的一个修改场景function deferredUpdatesA(fn: () A): A {const currentTime requestCurrentTime();const previousExpirationContext expirationContext;const previousIsBatchingInteractiveUpdates isBatchingInteractiveUpdates;expirationContext computeAsyncExpiration(currentTime); // 这里isBatchingInteractiveUpdates false;try {return fn();} finally {expirationContext previousExpirationContext;isBatchingInteractiveUpdates previousIsBatchingInteractiveUpdates;}
}expirationContext computeAsyncExpiration(currentTime);可以看到 computeAsyncExpiration 这个函数对其进行修改赋值 还有一种场景, 往下进行搜索function syncUpdatesA, B, C0, D, R(fn: (A, B, C0, D) R,a: A,b: B,c: C0,d: D,
): R {const previousExpirationContext expirationContext;expirationContext Sync; // 变成了 Synctry {return fn(a, b, c, d); // 这里是 setState 操作} finally {expirationContext previousExpirationContext; // 最终还原}
}syncUpdates 在 ReactDOM.js 中的 flushSync API flushSync: DOMRenderer.flushSync 一直溯源往上找到 ReactFiberScheduler.js 中的 flushSync这个就是 本源的 flushSync// TODO: Batching should be implemented at the renderer level, not within
// the reconciler.
function flushSyncA, R(fn: (a: A) R, a: A): R {invariant(!isRendering,flushSync was called from inside a lifecycle method. It cannot be called when React is already rendering.,);const previousIsBatchingUpdates isBatchingUpdates;isBatchingUpdates true;try {return syncUpdates(fn, a); // 这里} finally {isBatchingUpdates previousIsBatchingUpdates;performSyncWork();}
}上述调用的是 syncUpdates在之前的示例中如下flushSync(() {this.setState({num: newNum,})
})上述示例就是传入 fn 回调, 内部调用 setState在这种场景下 expirationTime 变成了 Sync 以上两种情况 是给 expirationContext 进行赋值 2 当 expirationTime 变成了 Sync 就不符合第一种情况了这时候往下走匹配到了 isWorking isWorking 表示有任务正在更新也是基于条件指定某个值这块涉及到后续任务的更新跳过 3 没有外部强制的情况下 if (fiber.mode ConcurrentMode)判断 fiber.mode 是否是 ConcurrentMode找到 ConcurrentMode 的定义处 ReactTypeOfMode.jsexport type TypeOfMode number;export const NoContext 0b000;
export const ConcurrentMode 0b001;
export const StrictMode 0b010;
export const ProfileMode 0b100;可见使用二进制方式来定义的可以通过 与或 这类逻辑的操作非常方便的组合 Mode以及判断是否有某个Mode例如const a 0b000;
const b 0b001;
const c 0b010;
const d 0b100;
let mode a; // 默认等于 a, 在后续渲染时并不知道是否有更改过
mode b // 如果 结果为 0 表示没有过b这种情况
mode | b // 这样给 mode 增加 b这时候 mode 变成1就对应了 b
mode | c // 给 mode 增加 c, 这时候 mode 变成 3也就是 0b011
mode b // 这时候判断mode是否有b, 如果是1则有b 结果是1 对应b
mode c // 这时候判断mode是否有c, 如果是1则有c, 结果是2 对应c这是一种巧妙的设计方式类似的在 ReactSideEffectTags.js 中也是这么设计的 回到代码里如果是 ConcurrentMode 才会调用computeInteractiveExpiration 和 computeAsyncExpiration 两个函数中的一个计算 expirationTimeif (isBatchingInteractiveUpdates) {// This is an interactive updateexpirationTime computeInteractiveExpiration(currentTime);
} else {// This is an async updateexpirationTime computeAsyncExpiration(currentTime);
}关于 isBatchingInteractiveUpdates 在 interactiveUpdates 函数中被赋值为 true 大部分的 React 事件产生的更新事件中绑定回调函数这个回调函数执行的时候大部分都是在 interactiveUpdates 情况下也就是 isBatchingInteractiveUpdates 为 true 时 后面 expirationTime 1; 是为了区分下一个即将进行的更新和当前正在创造的更新防止一样强制把当前1 如果不属于则还是 Sync