React expirationTime的计算过程

491 阅读1分钟
function computeExpirationForFiber(currentTime, fiber){
    const mode = fiber.mode;
    if ((mode & BlockingMode) === NoMode) {
        return Sync;
    }
    
    switch (priorityLevel) {
        case ImmediatePriority:
            expirationTime = Sync;
            break;
        case UserBlockingPriority:
            expirationTime = computeInteractiveExpiration(currentTime);
            break;
        case NormalPriority:
        case LowPriority:
            expirationTime = computeAsyncExpiration(currentTime);
            break;
        case IdlePriority:
            expirationTime = Idle;
            break;
        default:
            invariant(false, 'Expected a valid priority level');
    }
}

computeInteractiveExpirationcomputeAsyncExpiration都是采用下面的最终公式计算得到的,差别在于$p_1$$p_2$的值不同。computeInteractiveExpiration$p_1$$p_2$的值更小,得到的结果就更大。

    m = 2^{30} - 3

    c = m - n
    
    c_1 = m - c + \frac {p_1} {10} = n + \frac {p_1} {10}
    
    c_2 = \frac {p_2} {10}
    
    r = [ \frac {c_1} {c_2} + 1]c_2

    e = m - r

    e = m - [ \frac {c_1} {c_2} + 1]c_2

    e = m - [ \frac {n + \frac {p_1} {10} } {\frac {p_2} {10}} + 1]\frac {p_2} {10}     ······  (最终公式)
    

其中

$m$ 表示 MAGIC_NUMBER_OFFSET

$c$ 表示 currentTime

$n$ 表示 now(),可以理解为Date.now() / 10

$p_1$ 表示 _PRIORITY_EXPIRATION

$p_2$ 表示 _PRIORITY_BATCH_SIZE

$e$ 表示 expirationTime

$c_1$$c_2$$r$为中间值, 中括号表示取整

expirationTime值越大,优先级越高 在React中一个单位的expirationTime表示10ms, 从最终公式中可以看到

WechatIMG71799.jpeg

LOW_PRIORITY_BATCH_SIZE$p_1= 250$为例,now() 在0到25(25个单位,表示250ms)之间计算得到的过期时间相同,他们将产生的更新将合并到一起,$p_2$越小,更新粒度就越小,LOW_PRIORITY_BATCH_SIZE将250ms产生的更新合并到一起,HIGH_PRIORITY_BATCH_SIZE将100ms产生的更新合并到一起