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