Skip to content
目录

requestWork的最后,调用了performSyncWork(同步任务)和scheduleCallbackWithExpirationTime,其中,scheduleCallbackWithExpirationTime最后调用的函数是performAsyncWork(异步任务);

performSyncWork

typescript
function performSyncWork() {
  performWork(Sync, false);
}

performAsyncWork

typescript
function performAsyncWork() {
  try {
    if (!shouldYieldToRenderer()) {
      // 如果进入到此回调
      // 说明当前执行的回调已经超时,也就是说最近的更新过期了
      if (firstScheduledRoot !== null) {
        recomputeCurrentRendererTime();
        let root: FiberRoot = firstScheduledRoot;
        do {
          didExpireAtExpirationTime(root, currentRendererTime);
          root = (root.nextScheduledRoot: any);
        } while (root !== firstScheduledRoot);
      }
    }
    performWork(NoWork, true);
  } finally {
    didYield = false;
  }
}

performSyncWork和performAsyncWork最后调用的其实都是performWork,唯一的区别就在第二个参数isYieldy的区别上,isYieldy代表的是当前任务可中断

performWork

typescript
function performWork(minExpirationTime: ExpirationTime, isYieldy: boolean) {
  // 找到优先级更高的那个FiberRoot和他的时间
  // 赋值给 nextFlushedRoot 和 nextFlushedExpirationTime
  findHighestPriorityRoot();
  // 判断isYieldy 为异步任务会走到这里来
  if (isYieldy) {
    // 异步任务,重新计算currentSchedulerTime
    recomputeCurrentRendererTime();
    currentSchedulerTime = currentRendererTime;
    while (
      nextFlushedRoot !== null &&
      nextFlushedExpirationTime !== NoWork &&
      minExpirationTime <= nextFlushedExpirationTime &&
      !(didYield && currentRendererTime > nextFlushedExpirationTime)
    ) {
      // 这里的条件的意思是
      // 下一个待执行的FiberRoot不是null 并且 nextFlushedExpirationTime 不等于NoWork
      // minExpirationTime小于或等于nextFlushedExpirationTime;一般情况下两者是相等的
      // !(didYield && currentRendererTime > nextFlushedExpirationTime)
      // 这个条件 就是说,didYield 为false 或者 
      // currentRendererTime > nextFlushedExpirationTime 不成立
      // 也就是 时间片还有时间,但是当前任务已经超时了 会进入此判断
      // 还有就是一贞的时间执行完了 当前任务没超时 会进入次判断
      // 当前渲染时间是否大于nextFlushedExpirationTime,也就是判断任务是否已经超时了了,
      // 如果超时了,根据下面调用performWorkOnRoot的参数中
      // 有一个currentRendererTime > nextFlushedExpirationTime,
      // 也就是这种情况下为true,代表的意思是同步执行任务不再判断是否时间片到期。
      performWorkOnRoot(
        nextFlushedRoot,
        nextFlushedExpirationTime,
        currentRendererTime > nextFlushedExpirationTime,
      );
      findHighestPriorityRoot();
      recomputeCurrentRendererTime();
      currentSchedulerTime = currentRendererTime;
    }
  } else {
    // 同步的情况
    while (
      nextFlushedRoot !== null &&
      nextFlushedExpirationTime !== NoWork &&
      minExpirationTime <= nextFlushedExpirationTime
    ) {
      // while循环的意思是什么呢?
      // 下一个待执行的FiberRoot不是null 并且 nextFlushedExpirationTime不是NoWork
      // 并且 minExpiration 小于或等于 nextFlushedExpirationTime
      // 在同步任务的时候 nextFlushedExpirationTime 就是等于minExpiration 等于NoWork
      // 只有当FiberRoot上的任务都执行完了  就会跳出while循环
      performWorkOnRoot(nextFlushedRoot, nextFlushedExpirationTime, false);
      findHighestPriorityRoot();
    }
  }
  
  if (isYieldy) {
    callbackExpirationTime = NoWork;
    callbackID = null;
  }

  if (nextFlushedExpirationTime !== NoWork) {
    scheduleCallbackWithExpirationTime(
      ((nextFlushedRoot: any): FiberRoot),
      nextFlushedExpirationTime,
    );
  }
}

performWorkOnRoot

说明

这里的root指的是FiberRoot, 也就是说,react的渲染是从FiberRoot开始的

typescript
function performWorkOnRoot(
  root: FiberRoot,
  expirationTime: ExpirationTime,
  isYieldy: boolean,
) {

  isRendering = true;

  if (!isYieldy) {
    // 同步任务和异步的超时任务会走到这
    let finishedWork = root.finishedWork;
    if (finishedWork !== null) {
      // 如果存在 说明render过程完成 可以commit了
      completeRoot(root, finishedWork, expirationTime);
    } else {
      root.finishedWork = null;
      // 在任务被挂起的时候通过setTimeout设置的返回内容,
      // 用来下一次如果有新的任务挂起时清理还没触发的timeout
      const timeoutHandle = root.timeoutHandle;
      if (timeoutHandle !== noTimeout) {
        root.timeoutHandle = noTimeout;
        cancelTimeout(timeoutHandle);
      }
      renderRoot(root, isYieldy);
      finishedWork = root.finishedWork;
      if (finishedWork !== null) {
        completeRoot(root, finishedWork, expirationTime);
      }
    }
  } else {
    // 执行异步任务
    let finishedWork = root.finishedWork;
    if (finishedWork !== null) {
      completeRoot(root, finishedWork, expirationTime);
    } else {
      root.finishedWork = null;
      const timeoutHandle = root.timeoutHandle;
      if (timeoutHandle !== noTimeout) {
        root.timeoutHandle = noTimeout;
        cancelTimeout(timeoutHandle);
      }
      renderRoot(root, isYieldy);
      finishedWork = root.finishedWork;
      if (finishedWork !== null) {
        // 首先检查当前一贞的时间片还有没有时间
        // 如果时间不够,就留到下一帧处理,如果时间还有,就执行commit
        if (!shouldYieldToRenderer()) {
          completeRoot(root, finishedWork, expirationTime);
        } else {
          root.finishedWork = finishedWork;
        }
      }
    }
  }
  isRendering = false;
}

performWorkOnRoot主要是从FiberRoot节点开始执行,分为2个阶段:

  1. 渲染阶段(renderRoot)
  2. 提交阶段(completeRoot)

备案号: 浙ICP备2023000081号