大家好,我是Kason。想必大家都知道React有一个基于Fiber架构的调度系统。该调度系统的基本功能包括:更新具有不同的优先级。更新可能涉及多个组件的呈现。这些渲染可以分配给多个宏任务来执行(即,时间分片)。高优先级更新会打断正在进行的低优先级更新本文将用100行代码来实现这个调度系统,让你快速了解React的调度原理。我知道你不喜欢看大段代码,所以本文将以图表+代码片段的形式讲解原理。文末有完整的在线Demo,大家可以自己玩玩。打开!欢迎加入人类优质前端框架群。我们用work的数据结构来表示一个工作,work.count代表这个工作需要重复某件事的次数。demo中要重复的是“执行insertItem方法将插入到页面中”:constinsertItem=(content:string)=>{constele=document.createElement('span');ele.innerText=`${content}`;contentBox.appendChild(ele);};因此,对于下面的工作:constwork1={count:100}意思是:执行100次insertItem,在页面中插入100个。work可以类比为React的一次更新,work.count就像这次更新要渲染的组件数量。所以Demo是类比React的更新过程来实现第一版的调度系统。流程如图:包括三步:将workschedule方法插入到workList队列中(用来保存所有工作),从workList中取出工作,传递给performperform方法执行后重复步骤2完成所有工作。代码如下://保存所有工作队列constworkList:work[]=[];//调度函数schedule(){//从队列尾部获取一个工作constcurWork=workList.流行音乐();如果(curWork){执行(curWork);}}//执行函数perform(work:Work){while(work.count){work.count--;插入项目();}schedule();}给按钮绑定点击交互,最基本的调度系统就完成了:button.onclick=()=>{workList.unshift({count:100})schedule();}点击按钮插入100。React类比是:点击按钮,触发同步更新,渲染100个组件。接下来,我们将其转化为异步。SchedulerReact内部使用Scheduler完成异步调度。调度程序是一个独立的包。所以我们可以利用他来改造我们的Demo。Scheduler预设了5个优先级,从上到下递减:ImmediatePriority,同步优先级最高,UserBlockingPriorityNormalPriorityLowPriorityIdlePriority,优先级最低。scheduleCallback方法接收优先级和回调函数fn,用于调度fn://回调函数fn调度scheduleCallback(LowPriority,fn),优先级为LowPriority,在Scheduler内部。执行scheduleCallback后,会生成task的数据结构:consttask1={expiration:startTime+timeout,callback:fn}task1.expiration表示task1的过期时间,Scheduler会先执行过期的task.callback。expiration中的startTime为当前开始时间,不同优先级的超时时间不同。比如ImmediatePriority的timeout为-1,因为:startTime-1
