Skip to content

[Note] react从调度到更新的简单流程 #2

@ddzy

Description

@ddzy

expirationTime产生时机

react产生更新的方式有两种:

  • ReactDOM.render
  • setState

每产生一个新的更新, 会计算出一个对应的expirationTime.

比如, 调用ReactDOM.render的过程中:

  // ! MARK: [current] - FiberRoot.RootFiber
  const current = container.current;

  // ! MARK: [currentTime] - 是`动态`的, 表示页面从js开始加载到当前的时间戳
  const currentTime = requestCurrentTime();

  // ! MARK: [expirationTime] - 非常重要, `concurrent`根据其来进行优先级更新调度, 值越小, 优先级越高
  // ? 此处存在疑问, react在后续的expirationTime比对过程中, 比如经典的任务优先级机制
  // ? 是以大的expirationTime作为优先级更高的任务, 这就很尴尬了, 不知道是react自身的问题
  // ? 还是我理解出现偏差, 后续再做定夺...
  const expirationTime = computeExpirationForFiber(currentTime, current);
  return updateContainerAtExpirationTime(
    element,
    container,
    parentComponent,
    expirationTime,
    callback,
  );

Fiber的分片机制

PS: React的调度是以FiberRoot为基点

对于分片机制, 今早看到的一篇文章, 说的不错:

https://segmentfault.com/a/1190000019592928

1. 每个Fiber产生的更新, 会更新当前FiberexpirationTimechildExpirationTime

2. 然后迭代Fiber树(单向链表树结构), 找到FiberRoot

上述两步的主要代码如下所示:

function scheduleWork(fiber, expirationTime) {
    // 寻找FiberRoot, 更新childExpirationTime
    const root = scheduleWorkToRoot(fiber, expirationTime);
    
    if (
        // If we're in the render phase, we don't need to schedule this root
        // for an update, because we'll do it before we exit...
        !isWorking ||
        isCommitting ||
        // ...unless this is a different root than the one we're rendering.
        nextRoot !== root
    ) {
        // 请求调度
        const rootExpirationTime = root.expirationTime;
        requestWork(root, rootExpirationTime);
    }
}

3. 将FiberRoot添加到调度队列

function requestWork(FiberRoot, rootExpirationTime) {
    // 添加`FiberRoot`到调度队列
    addRootToSchedule(root, expirationTime);

    // ...

    // 根据五种不同的expirationTime, 进行performWork
    // NoWork -> 0
    // Never  ->  1
    // Interactive  ->  100 - 150
    // Async  ->  250 - 5000
    // Sync  ->  Number.MAXINTEGER
    if (expirationTime === Sync) {
        performSyncWork();
    } else {
        scheduleCallbackWithExpirationTime(root, expirationTime);
    }
}

单链表树状结构

何为 单链表树状结构 ? 既像二叉树, 又像单链表? 着实挺难理解

我个人的分析是, 所谓的 单链表树状, 指的是某个节点最多只能存在一个子节点、兄弟节点以及父节点, 以 React 为例, 其 fiber 树就采用了这种结构:

  • fiber.return -> 父节点
  • fiber.sibling -> 兄弟节点
  • fiber.child -> 子节点

一图胜千言:

10-单链表树状结构

Metadata

Metadata

Assignees

No one assigned

    Labels

    note简单笔记

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions