在前面的文章里有提到,在创建更新的时候,会有一个ExpirationTime的变量,在这章里我们了解一下它的计算方式和作用是什么。
1. ExpirationTime计算方式
先让我们来回顾一下代码:
export function updateContainer(
element: ReactNodeList,
container: OpaqueRoot,
parentComponent: ?React$Component<any, any>,
callback: ?Function,
): ExpirationTime {
const current = container.current;
const currentTime = requestCurrentTime();
const expirationTime = computeExpirationForFiber(currentTime, current);
return updateContainerAtExpirationTime(
element,
container,
parentComponent,
expirationTime,
callback,
);
}
computeExpirationForFiber
函数接受currentTime, current
两个参数,通过一系列的计算方式,返回了一个expirationTime。current很明显是指当前的fiber对象,那么currentTime
又是什么呢?currentTime
也有一个计算方式,这里我们可以先认为它是由一个js加载的时间经过一系列运算得到的一个常量。我们看看computeExpirationForFiber
做了什么。
代码我就不放了。因为函数里涉及到了很多函数外的变量,单纯放一个函数也很难看懂,我这里大概概括一下函数的计算方法。根据currentTime
以及一系列常量计算出来一个expirationTime,
MAGIC_NUMBER_OFFSET +
ceiling(
currentTime - MAGIC_NUMBER_OFFSET + expirationInMs / UNIT_SIZE,
bucketSizeMs / UNIT_SIZE,
)
大概解释一下这个公式,根据优先级的高低,会获取不一样的常量,当前fiber标记优先级的那个属性,代表的优先级越高,常量的数值越小,导致计算出来的expirationTime
也会越小,react就会率先调度这个相应的更新。公式里还有一个除法取整的操作,会导致相近的currentTime的fiber计算出来的expirationTime
相同的情况,就像11/3和10/3他们取整得到的数是一样的。那为什么要用这样的计算方式呢,因为好比在很短的时间内调用多次setState,如果多次算出来的expirationTime
都不一样,那么各个任务的优先级就会不一样,就会让react在短时间内进行多次更新,造成很大的性能问题。
2. ExpirationTime种类
ExpirationTime优先级分三种情况,不同的情况下计算出来的ExpirationTime不同。
- sync模式
- 异步模式(会设置一个过期时间,超过过期时间强制执行更新)
- 指定context