1 )概述
2 )源码
function requestCurrentTime() {
// requestCurrentTime is called by the scheduler to compute an expiration
// time.
//
// Expiration times are computed by adding to the current time (the start
// time). However, if two updates are scheduled within the same event, we
// should treat their start times as simultaneous, even if the actual clock
// time has advanced between the first and second call.
// In other words, because expiration times determine how updates are batched,
// we want all updates of like priority that occur within the same event to
// receive the same expiration time. Otherwise we get tearing.
//
// We keep track of two separate times: the current "renderer" time and the
// current "scheduler" time. The renderer time can be updated whenever; it
// only exists to minimize the calls performance.now.
//
// But the scheduler time can only be updated if there's no pending work, or
// if we know for certain that we're not in the middle of an event.
if (isRendering) {
// We're already rendering. Return the most recently read time.
return currentSchedulerTime;
}
// Check if there's pending work.
findHighestPriorityRoot();
if (
nextFlushedExpirationTime === NoWork ||
nextFlushedExpirationTime === Never
) {
// If there's no pending work, or if the pending work is offscreen, we can
// read the current time without risk of tearing.
recomputeCurrentRendererTime();
currentSchedulerTime = currentRendererTime;
return currentSchedulerTime;
}
// There's already pending work. We might be in the middle of a browser
// event. If we were to read the current time, it could cause multiple updates
// within the same event to receive different expiration times, leading to
// tearing. Return the last read time. During the next idle callback, the
// time will be updated.
return currentSchedulerTime;
}
isRendering
的时候,会直接返回 currentSchedulerTime
, 这个 schedulerTime
isRendering
只有在 performWorkOnRoot
的时候才被设置为 truecurrentSchedulerTime
currentSchedulerTime
currentSchedulerTime
就是在调用 performWorkOnRoot 之前算出来的时间if (isRendering) return currentScheudlerTime
的设定findHighestPriorityRoot
找到调度队列中,优先级最高的任务if (nextFlushedExpirationTime === NoWork || nextFlushedExpirationTime === Never)
recomputeCurrentRendererTime();
currentSchedulerTime = currentRendererTime;
batchedUpdates
里面类似
requestCurrentTime
都去计算一个时间1 ) 概述
recomputeCurrentRendererTime
2 )源码
// /packages/react-reconciler/src/ReactFiberScheduler.js
function recomputeCurrentRendererTime() {
const currentTimeMs = now() - originalStartTimeMs;
currentRendererTime = msToExpirationTime(currentTimeMs);
}
// packages/react-reconciler/src/ReactFiberExpirationTime.js
// 1 unit of expiration time represents 10ms.
export function msToExpirationTime(ms: number): ExpirationTime {
// Always add an offset so that we don't clash with the magic number for NoWork.
// ms / UNIT_SIZE 为了防止 10ms 之内的误差,两个时间差距在10ms以内,两个时间看做一致,最终计算出来的优先级也是一致
return ((ms / UNIT_SIZE) | 0) + MAGIC_NUMBER_OFFSET; // UNIT_SIZE 是 10, const MAGIC_NUMBER_OFFSET 是 2
}
function computeExpirationBucket(
currentTime,
expirationInMs,
bucketSizeMs,
): ExpirationTime {
return (
MAGIC_NUMBER_OFFSET +
ceiling(
currentTime - MAGIC_NUMBER_OFFSET + expirationInMs / UNIT_SIZE,
bucketSizeMs / UNIT_SIZE,
)
);
}
export function expirationTimeToMs(expirationTime: ExpirationTime): number {
return (expirationTime - MAGIC_NUMBER_OFFSET) * UNIT_SIZE;
}
currentTime - MAGIC_NUMBER_OFFSET
expirationTimeToMs
把这个时间转回来