react-reconciler/ReactFiberExpirationTime.js解析

React的fiber调度和expirationTime有着密不可分的联系,expirationTime决定着每个任务的优先级。一个expirationTime就是一个10ms的时间单位。
源码不长,我们先看源码,然后逐一分析每个函数。

import MAX_SIGNED_31_BIT_INT from './maxSigned31BitInt';

import {
  ImmediatePriority,
  UserBlockingPriority,
  NormalPriority,
  IdlePriority,
} from './SchedulerWithReactIntegration';

export const NoWork = 0;
export const Never = 1;
export const Sync = MAX_SIGNED_31_BIT_INT;
export const Batched = Sync - 1;

const UNIT_SIZE = 10;
const MAGIC_NUMBER_OFFSET = Batched - 1;

// 1 unit of expiration time represents 10ms.
export function msToExpirationTime(ms) {
  // Always add an offset so that we don't clash with the magic number for NoWork.
  return MAGIC_NUMBER_OFFSET - ((ms / UNIT_SIZE) | 0);
}

export function expirationTimeToMs(expirationTime) {
  return (MAGIC_NUMBER_OFFSET - expirationTime) * UNIT_SIZE;
}

function ceiling(num, precision) {
  return (((num / precision) | 0) + 1) * precision;
}

function computeExpirationBucket(
  currentTime,
  expirationInMs,
  bucketSizeMs,
) {
  return (
    MAGIC_NUMBER_OFFSET -
    ceiling(
      MAGIC_NUMBER_OFFSET - currentTime + expirationInMs / UNIT_SIZE,
      bucketSizeMs / UNIT_SIZE,
    )
  );
}

// TODO: This corresponds to Scheduler's NormalPriority, not LowPriority. Update
// the names to reflect.
export const LOW_PRIORITY_EXPIRATION = 5000;
export const LOW_PRIORITY_BATCH_SIZE = 250;

export function computeAsyncExpiration(
  currentTime,
) {
  return computeExpirationBucket(
    currentTime,
    LOW_PRIORITY_EXPIRATION,
    LOW_PRIORITY_BATCH_SIZE,
  );
}

export function computeSuspenseExpiration(
  currentTime,
  timeoutMs,
) {
  // TODO: Should we warn if timeoutMs is lower than the normal pri expiration time?
  return computeExpirationBucket(
    currentTime,
    timeoutMs,
    LOW_PRIORITY_BATCH_SIZE,
  );
}

// We intentionally set a higher expiration time for interactive updates in
// dev than in production.
//
// If the main thread is being blocked so long that you hit the expiration,
// it's a problem that could be solved with better scheduling.
//
// People will be more likely to notice this and fix it with the long
// expiration time in development.
//
// In production we opt for better UX at the risk of masking scheduling
// problems, by expiring fast.
export const HIGH_PRIORITY_EXPIRATION = __DEV__ ? 500 : 150;
export const HIGH_PRIORITY_BATCH_SIZE = 100;

export function computeInteractiveExpiration(currentTime) {
  return computeExpirationBucket(
    currentTime,
    HIGH_PRIORITY_EXPIRATION,
    HIGH_PRIORITY_BATCH_SIZE,
  );
}

export function inferPriorityFromExpirationTime(
  currentTime,
  expirationTime,
) {
  if (expirationTime === Sync) {
    return ImmediatePriority;
  }
  if (expirationTime === Never) {
    return IdlePriority;
  }
  const msUntil =
    expirationTimeToMs(expirationTime) - expirationTimeToMs(currentTime);
  if (msUntil <= 0) {
    return ImmediatePriority;
  }
  if (msUntil <= HIGH_PRIORITY_EXPIRATION + HIGH_PRIORITY_BATCH_SIZE) {
    return UserBlockingPriority;
  }
  if (msUntil <= LOW_PRIORITY_EXPIRATION + LOW_PRIORITY_BATCH_SIZE) {
    return NormalPriority;
  }

  // TODO: Handle LowPriority

  // Assume anything lower has idle priority
  return IdlePriority;
}

在16.8.6版本的React中,expirationTime采用了减法策略。pr: Flip expiration times。所以现在的expirationTime越大,优先级越高。

  • msToExpirationTimemsToExpirationTime从ms时间戳到expirationTime的转换
  • ceiling以某个精度范围向上取整。
  • computeExpirationBucket为了计算在某个bucket精度内的expirationTime,输入不同的expirationInMs,bucketSizeMs参数可以定义不同优先级的expirationTime
  • computeAsyncExpiration是一个计算可以中断的任务的低优先级expirationTime的函数,内部调用了computeExpirationBucket
  • computeInteractiveExpiration是一个计算不可以中断的任务的高优先级expirationTime的函数,内部调用了computeExpirationBucket
  • inferPriorityFromExpirationTime:通过把expirationTimecurrentTime化为ms单位,并计算他们的差值,通过判断差值落在哪个区间去判断属于哪个优先级。主要分为四个优先级:ImmediatePriority: <=0;UserBlockingPriority: 0 ~ (HIGH_PRIORITY_EXPIRATION + HIGH_PRIORITY_BATCH_SIZE);NormalPriority: (HIGH_PRIORITY_EXPIRATION + HIGH_PRIORITY_BATCH_SIZE) ~ (LOW_PRIORITY_EXPIRATION + LOW_PRIORITY_BATCH_SIZE);
    其他情况就是IdlePriority

你可能感兴趣的:(react-reconciler/ReactFiberExpirationTime.js解析)