Context ExpirationTime = context update = context Update = context Update = context Update = context Update React sets a ExpirationTime. When a ExpirationTime is ExpirationTime, if an update has not been executed, React will force that update. That’s what ExpirationTime does.

Reactdom.render (); reactdom.render (); updateContainer();

export function updateContainer(

  element: ReactNodeList,

  container: OpaqueRoot,

parentComponent: ? React$Component<any, any>,

callback: ? Function,

) :ExpirationTime 
{

.

   // Calculate the expiration time. This is a very important point for React priority updates

  const expirationTime = computeExpirationForFiber(

    currentTime,

    current,

    suspenseConfig,

  );

.

}

Copy the code

ComputeExpirationForFiber:

// Calculate expirationTime for fiber objects

export function computeExpirationForFiber(

  currentTime: ExpirationTime,

  fiber: Fiber,

  suspenseConfig: null | SuspenseConfig,

) :ExpirationTime 
{

.

  // Compute an expiration time based on the Scheduler priority.

    switch (priorityLevel) {

      case ImmediatePriority:

        expirationTime = Sync;

        break;

      case UserBlockingPriority:

        // TODO: Rename this to computeUserBlockingExpiration

        // One is to calculate the expiration time of interactive events such as clicks

        expirationTime = computeInteractiveExpiration(currentTime);

        break;

      case NormalPriority:

      case LowPriority: // TODO: Handle LowPriority

        // TODO: Rename this to... something better.

        // One is to calculate the expiration time of asynchronous updates

        expirationTime = computeAsyncExpiration(currentTime);

        break;

      case IdlePriority:

        expirationTime = Never;

        break;

      default:

        invariant(false.'Expected a valid priority level');

    }

.

}

Copy the code

We can see that there are two calculation expirationTime method, respectively computeInteractiveExpiration () and computeAsyncExpiration ()

Look at the first computeAsyncExpiration ()

ComputeAsyncExpiration () returns a expirationTime with a lower priority (common asynchronous updates).

Source:

// Expiration time of low permissions

export const LOW_PRIORITY_EXPIRATION = 5000;

export const LOW_PRIORITY_BATCH_SIZE = 250;

// Normal asynchronous expirationTime

export function computeAsyncExpiration(

  currentTime: ExpirationTime,

) :ExpirationTime 
{

  return computeExpirationBucket(

    currentTime,

    / / 5000

    LOW_PRIORITY_EXPIRATION,

    / / 250

    LOW_PRIORITY_BATCH_SIZE,

  );

}

Copy the code

LOW_PRIORITY_BATCH_SIZE LOW_PRIORITY_BATCH_SIZE LOW_PRIORITY_BATCH_SIZE

ComputeExpirationBucket () function: Calculate expiration time

Source:

/ / 1073741823

export const Sync = MAX_SIGNED_31_BIT_INT;

/ / 1073741822

export const Batched = Sync - 1;



const UNIT_SIZE = 10;

/ / 1073741821

const MAGIC_NUMBER_OFFSET = Batched - 1;



function ceiling(num: number, precision: number) :number {

  return (((num / precision) | 0) + 1) * precision;

}



// Calculate the expiration time

function computeExpirationBucket(

  currentTime,

  expirationInMs,

  bucketSizeMs,

) :ExpirationTime 
{

  return (

    / / 1073741821

    MAGIC_NUMBER_OFFSET -

    ceiling(

      // 1073741821-currentTime+(high 150 or Low 5000/10),

      MAGIC_NUMBER_OFFSET - currentTime + expirationInMs / UNIT_SIZE,

      //(high 100 or low 250/10)

      bucketSizeMs / UNIT_SIZE,

    )

  );

}

Copy the code

(1) MAX_SIGNED_31_BIT_INT

// Max 31 bit integer. The max integer size in V8 for 32-bit systems.

// Math.pow(2, 30) - 1

// 0b111111111111111111111111111111

// The maximum integer value, which is the maximum value set in V8 for 32-bit systems

export default 1073741823;

Copy the code

(2) | 0 means integer

console.log(16/3 |0/ / 5

Copy the code

(3) Calculate the expiration time of asynchronous updates according to the formula in computeExpirationBucket() :

   / / low

  1073741821-ceiling(1073741821-currentTime+500.25)



  1073741821- ((((1073741821-currentTime+500) / 25) | 0) + 1) * 25



  1073741821- ((1073741821/25-currentTime/25+20 | 0) + 1) * 25



  1073741821- ((1073741821/25-currentTime/25+20*25/25 | 0) + 1) * 25



  1073741821- ((1073741821-currentTime+500) /25 | 0) *25 - 25



  1073741796- ((1073741821-currentTime+500) /25 | 0) *25



  1073741796- ((1073742321-currentTime)/25 | 0) *25

  //====== we take the last four digits directly to explore the pattern ===================

  1796- ((2321-currentTime)/25 | 0) *25

  // Assume currentTime is 2000

  1796- (23212000 /25 | 0) *25 / / 1796-300

  / / currentTime is 2010

  1796- (311/25 | 0) *25 / / 1796-300

  / / currentTime is 2024

  1796- (311/25 | 0) *25 / / 1796-275

  / / currentTime is 2025

  1796- (311/25 | 0) *25 / / 1796-275

Copy the code

As you can see, the low priority expiration interval is 25ms and the high priority expiration interval is 10ms

  / / high

  1073741821-ceiling(1073741821-currentTime+15.10)

Copy the code

React updates with a lower priority have a expirationTime interval of 25ms. React allows two similar updates to have the same expirationTime. The LOW_PRIORITY_BATCH_SIZE name automatically merges batch updates.

Imagine a developer constantly updating the ReactApp with setState(), which would have a serious impact on performance if similar updates were not merged. Like the doubleBuffer, React was considered to improve performance!

Making: github.com/AttackXiaoJ…


(after)