Skip to content

Suspense 实现

Suspense 实现

  1. beginWork时,遇到Suspense,默认是正常显示组件:创建一个OffScreenComponent来表示,此时visibletrue
  2. 当加载到组件内部的promise时,由于第一次渲染,此时还未加载完成,会报错,抛出promise
  3. handleError捕捉到错误,首先开始throwException
    1. 标记报错的fiber.flagsIncomplete
    2. 向上查找,找到第一个Suspense
    3. Suspense.updateQueue中添加报错信息(也就是抛出的promise)。
    4. 通过attachPingListener方法执行该promise,并在then回调里添加一个更新任务。
    5. 标记Suspense fiber flagsShouldCapture
  4. 从报错的fiber开始,执行completeWork
    1. 向上找到ShouldCaptureSuspense,标记为DidCapture
    2. 查找过程中遇到的fiber,标记为Incomplete
    3. 返回最终的fiberSuspense或者HostRoot(没找到Suspense)。
  5. 对找到的Suspense重新开始beginWork。此时DidCapturetrue,显示fallbackSuspensechild指向OffScreenComponent(内部包含主要的组件),OffScreenComponentsibling指向fallbackChildFragment(占位组件)。而真正进行渲染的是fallbackChildFragment
  6. completeWork的时候,对于Suspense fiber,检测到已经从显示primary(主组件)变为显示fallback(占位组件)。如果此时updateQueue存在,说明还有待更新的任务,标记fiberUpdate
  7. commitWork阶段,对于标记UpdateSuspense,会调用attachSuspenseRetryListeners将所有异步任务的then添加更新任务,对应的laneretryLane。(如果之前已经更新过了,那么不需要重复更新,这里只是作为保障)
  8. 等到promise加载完成,重新开始更新,此时就能正常的显示primary组件了。