React源码解析15-suspend&expirationTime

343 阅读3分钟

1.suspend

1.挂起某个任务,某次更新的任务暂时不提交即执行Beginwork,执行render阶段,但是不执行commitwok即commitwork

2.这次更新可能在下次更新执行

2.current和workingprogress区别

1.current和workingprogress是大部分属性一样,但是完全独立的两个对象

image-20210518091116521

在整个render阶段中 我们都是取创建新的workingprogress的子fiber树,current指向的fiber树表示上次的更新的fiber树,我们beginwork创建的都是workingprogress的新的fiber树,不会相互影响,当我们执行完

commitwork之后,root的current指向新形成的fiber即workingprogress,这时候workingprogress才和实际的dom是一一对应的,rootfiber因为没更新已经过时啦,后续更新会在workingprogress(此时的current)上面继续创建workingprogress.

image-20210518091504006

3.三种suspend的方式

1.把提交放到低优先级的任务上 这次更新不执行commitRoot 不更新 可能在低优先级任务执行的时候执行这次的updateQueue

2.没有低优先级的任务 则直接发起一个同步更新 会设置root的expirationTime为sync同步更新,然后会立马更新此次suspend 如果还是有错那么就出错 没错误就过

3.如果是有timeout形式的 即throw promise形式的 则在timeout时间后再强制执行commitWork更新

4.expitrationTime类型

1.pendingTime:

进入scheduleWork的任务都是pending的任务(等待更新的任务) 里面会对所有pending任务排序 找到root上最高优先级的任务

2.suspendedTime

同1 不过我们看的是root上的suspendTime 即被挂起的任务优先级排序

3.pingedTime

throw promise 会去找优先级最高的

5.expirationTime和nextExpirationTimeToWorkOn的区别

1.expirationTime作用于渲染前的,nextExpirationTimeToworkOn是渲染时的

root的expirationTime决定啦我们是否以异步还是异步的方式执行子树的更新,异步和同步的区别就是我们可以拿到一个deadline来判断异步任务是否过期,且是可中断的,同步任务就直接子树更新然后提交

总结:expirationTime主要作用就是在子树更新之前判断我们是否是同步/异步用时间片的方式更新

root.nextExpirationTimeToworkOn:从renderRoot开始有,作用是更新过程中确定我们这次渲染更新过程的任务优先级

一开始我们的nextRenderExpirationTime就=root.nextExpirationTimeToworkOn,nextRenderExpirationTime这个变量在很多地方使用,比如beginwork:他的renderExpiratime就是root.nextExpirationTimeToworkOn

root的nextExpirationTimeToworkOn 会在beginwork的时候作为renderExpirationTime,用来和每个fiber节点的expiratime比较判断该fiber节点此次是否要执行更新,每个fiber节点的expiratime就是classcmp中updateQueue中update最高优先级的expiratime。

以及renderExpirationTime会和update比较判断该update是否需要更新

renderExpirationTime所有地方就是root.nextExpirationTimeToworkOn

2.所以我们可以强制指定root.expirationTime = sync 来保证下次performWork时候是同步更新

指定root.nextExpirationTimeToWorkOn=expirationTime 指定下次的renderExpirationTime就是root的nextExpirationTimeToWorkOn保证下次执行的也是这个root且是同步模式。即下一次peroformWork执行时候也是这个root且是同步模式