最近,我最初计划发表有关巷道优先事项的文章,但这陷入了为什么React替换到乘车部分的到期时间的优先级。我在互联网上找到了大量搜索工作,但我很少找到有关此主题的详细信息。在目前,大多数文章都讨论了车道优先事项的出现问题,我发现切换到车道的原因不是这样。这篇文章将证明这一结论是react-16.12.0。
一切都必须从一个反应中谈论。一个哥哥在React的问题中提出了一个问题:关于Lanes的一些问题。可能是您的车道优先级的含义看起来很兴奋,但是您有任何例子要解释吗?此时,这是一个大型Man Inside React在codesandbox上发布了示例代码:在LAN之前。这可能是由于版本的问题,该代码和无法正常运行的问题。由于它涉及它,因此它也被许多文章视为一个示例。现在直接发布此代码:
实际上,该代码非常简单,使用承诺和悬疑来模拟io请求。悬疑,我可能会在这里提及该原则。当我们是悬念中的提升类型的异常加薪类型时,React将捕获这一诺言,并将悬念子批量的内容切换到sholdback.content.content.content.content.con.content.con.content.content。。具体过程是:
但是有时候,如果请求很快就完成,则在整个请求中会有一大幅退缩,并导致用户体验差。也认为此问题也被认为是考虑的。该挂钩被启动,可以将其传递到一个参数中以控制后备,以便可以延迟。将其设置为1S内的后回界面,如果请求在1S内完成,则将其设置为实际sub -page。直接显示,否则它将开始在1s.s.aflback Flash屏幕的现象之前展示后备。
此代码的运行结果如下:
点击按钮后,已发送请求,但目前尚未立即显示后备。在同一时间,计数也停止增加。在使用Useransition超时后,后备内容加载...这与我们的期望有点一致,但是一旦它不符合我们的期望:
但是,这真的是一项更高的IO任务,可以阻止低优先级CPU任务吗?
从上面的现象可以看出,我们的渲染任务确实被阻止了。但是现在有新的问题:
让我们进行一个实验以删除起始交流并保持悬念。我们会发现,当您删除startertransaction时,单击按钮立即显示加载...但是计数不会卡住。我们发现,当startertransaction保留悬疑时,该页面没有被子。并模拟了IO任务。因此,我们得出第一个结论:
该页面被卡住了,不是因为高度优先任务的障碍
目前,第一个问题尚未真正回答。我们现在知道阻止和渲染是其他人,但是这是什么?经过长时间的调试和阅读源代码后,阻止渲染的原因实际上是:
同时使用悬念和起动性
可以说这两个兄弟是必不可少的,但是任何人都不会被阻止。但是成熟的单词很好:我知道如果您很混乱,只需告诉我代码。源代码。
首先找到此功能。此功能的作用是基于它进行各种操作,然后将来呈现。注意到它已经达到了最终的diff提交阶段。如果我们同时使用悬疑和starttransaction,然后,存在status是在rootspendedwithdelay上进行的,此时代码将计算一个msuntilityout,表明时间来自startertransactions。
可以看出,MSUNTINGIEMOUT的回调是直接安排的。它直接基于呼叫。如果不调用跟随-up commitroot,自然就没有真正的dom更改。这次,其他需要提交的差异,您如何才能延迟我们的提交,我们必须受苦?是的,React是如此任意。即使在同一任务中还有其他差异,还有其他差异需要提交反应。这就是为什么我们单击按钮为什么要停止计数。。
这三个问题已经回答,但是我们还没有找到这个问题的本质。当渲染计数时,aikStatus设置为RootsuspendedwithDelay时发生了什么?条件Current.moizedState === null && workInprogress.momoizedstate!== null,将Outtatus设置为RootsuspendedWitchDeay:
那么,为什么我们在单击“单击我”按钮后单击此WIP.moizedstate呢?它不是空的吗?如果在功能中满足条件,它将最终输入:
这个分支将在这里。这就是为什么workInprogress.moiziedState在完整工作中没有空的原因。现在问题成为这种情况。什么时候可以满足这种情况?如前所述,如果我们想提出IO请求,我们必须首先付出诺言,并将被React捕获。如果您抓住了,您将在附近附近给出此效果tag。会击中,这将稍后导致渲染。在最后回到我写的代码,什么情况会抛出承诺:
换句话说,只要资源!==不确定的诺言将在解析之前就被抛出。资源是初始化为未定义的。当我们单击ONCLICK时,我们将致电:
也就是说,只要执行这一点,承诺将被抛出,这将导致最终的跳过渲染问题。因此,重点是。如果两个优先级相同,则反应将通过相同的任务来处理。目前,我们的代码中有两个:
因此,这两个设置的优先级是否相同,这会导致计数的渲染和悬念子节点在同一任务上呈现?这是正确的,我们终于找到了真实的答案!IntersectionSectionTrestection我们知道,如果它是的,那么由用户事件触发的SetState,React将根据事件类型选择不同的优先级。如果它是其他位置的SetState,例如Settimeout,React将使用默认优先级。并且存在相同的控制优先级操作,它将根据超时的长度来计算优先级。长度越长,优先级就越少。
因为计算计数状态和setResouce的优先级导致渲染计数作为处理悬念的任务实际上是相同的任务。这次,悬念需要延迟渲染,这导致渲染计数的任务。
在这一点上,我们基本上找到了该页面被阻塞的原因。尽管它与IO相关,但阻止低优先级的CPU任务确实不是高优先级的任务,因为这是因为它的优先级相同障碍物或跳过的两个任务。
当然,在知道问题的原因之后,我们也想知道如何解决这个问题。实际上,答案非常简单。由于原因是优先级与其他任务相同,因此我们只需要降低用Usetransition计算的优先级即可使其优先级少于任何其他任务。此想法也非常容易验证:因为用户点击为一个非常高的优先事件,我们在单击“ me”按钮触发setResource后继续单击按钮。
后备渲染也与我们的期望一致。原因也很好地解释了:
由于单击事件生成的渲染非常高的优先级,因此直接跳过了计算setTresource状态计算。因此,在渲染任务中,子组件的资源不确定。如果资源不确定,则没有抛弃承诺,并且自然不会延迟渲染后备。目前,可以正常更新计数。
至于为什么跳过SetResource,您可以参考我的其他文章:更新队列原理。
如此之多,车道可以解决这个问题吗?当然,巷道优先级由二进制位置控制,越靠近权利的人越高,优先级就越高。此问题是完美解决的。因此,确实可以做出反应,这确实是这样做的。?我只能说React的开发人员绝对比我更明智。让我们直接查看React 18.01中的优先定义定义的源代码:
计算代码时可以计算代码时可以采取的范围。可以看出,它的确比其他任务相比,它确实是左侧的。任务,甚至默认设备都大于所有过渡行。
现在,我想问本文的最终问题:
车道可以解决这个问题,因此从到期时间到车道解决此问题的反应是否改变了?
我的个人答案是:否。因为这个问题即使在到期时也得到了很好的解决:只要您设置了一个用户术来计算优先级的上限并确保它比其他优先级小。那么为什么lane的反应更改到期时间说实话,我还不能回答这个问题。也许只有React成员知道他们是真实的。
我们知道,经过分析,这不是车道优先级从到期时间切换的原因。我不知道具体原因。如果您认识大个子,您将在评论区域内有自己的观点。
多亏了Nero提供的React源代码调试环境,它给我带来了很多便利。Nero Boss对React也有深刻的了解。想要学习React源代码的合作伙伴需要戳戳GitHub React的秘密。
原始:https://juejin.cn/post/7095307142046941191