大家好,我是Kason。React这几年一直在完善的“并发模式”主要由以下两部分组成:基于纤程实现的可中断更新架构。基于调度器的优先级调度。可以说从2016年到今年年底(或明年初)React18发布正式版,fiber架构已经重构。这期间,React团队的大部分工作都是围绕这两点展开的。如果我告诉你,浏览器原生支持React多年来努力实现的“优先级调度”,你会感到惊讶吗?这篇文章参考了使用postTaskScheduler[1]构建更快的Web体验。什么是优先级调度假设我们有一个“日志记录”脚本需要在页面初始化后执行:initCriticalTracking();调用栈torch图如下:可以看到,这是一个执行了249.08ms的长任务。在执行过程中,浏览器会掉帧(表示为:浏览器冻结)。现在,我们将其包装在“优先级调度函数scheduler.postTask”的回调函数中:scheduler.postTask(()=>initCriticalTracking());长任务分解为多个短任务:每个任务之间浏览器有机会重排和重绘,减少掉帧的机会。这种“根据任务优先级拆解任务并分配执行时间的技术”就是“优先级调度”。scheduler.postTask[2]是Chrome实现的“优先级调度API”。scheduler.postTask是一个实验性的特性,需要在chrome://flags中打开#enable-experimental-web-platform-features如何实现优先级调度在scheduler.postTask出现之前,通常使用“willbeinAPIscalledatdifferentstages”模拟“优先级调度”,例如:requestAnimationFrame(简称rAF)一般用于处理动画,会在浏览器渲染前触发requestIdleCallback(简称rIC),在没有其他任务的每一帧空闲时间调用setTimeout、postMessage、MessageChannel在渲染之间触发React,使用MessageChannel实现优先级调度,setTimeout作为降级方案。不过这些API毕竟各有各的工作。用他们实现的“优先级调度”比较粗糙。为此,postTaskScheduler诞生了。postTaskSchedulerscheduler.postTask的使用有3个可选优先级:使用方法很简单,通过以下方式注册的回调函数会以“默认优先级”进行调度://defaultpriorityscheduler.postTask(()=>console.log('你好,postTask'));也可以指定优先级和执行延迟://调用后延迟执行1秒,优先级最低scheduler.postTask(()=>console.log('Hello,p??ostTask'),{delay:1000,priority:'背景',});postTask是建立在AbortSignalAPI[3]之上的,所以我们可以取消还在排队还没有执行的回调函数。通过使用TaskControllerAPI进行控制:constcontroller=newTaskController('background');window.addEventListener('beforeunload',()=>controller.abort());scheduler.postTask(()=>console.log('Hello,postTask'),{signal:controller.signal,});同时,实验性的schedule.wait方法可以让我们很方便的等待一定的时机再执行任务。比如我们可以在页面加载完成后异步加载xxx.js:asyncfunctionloadxxx(){//等待事件派发awaitscheduler.wait('myPageHasLoaded');returnimport('xxx.js');}//页面加载后调度事件window.dispatchEvent(newCustomEvent('myPageHasLoaded'));上面代码简化为postTask的事件配置项:scheduler.postTask(()=>import('xxx.js'),{event:'myPageHasLoaded'})总结“优先级调度”可以应用在很多领域,比如:资源提前、延迟请求第三方资源延迟加载……可以预见,这必然会增加未来前端编程的复杂度。就像过去,当Web应用复杂到一定程度时,出现了前端框架,开发者不需要直接操作DOM。未来,当“优先级调度”复杂到一定程度时,肯定会有一个集成的解决方案,让开发者不需要直接去操纵优先级。等等,这不就是React现在在做的事情吗?参考[1]使用postTaskScheduler构建更快的Web体验:https://medium.com/airbnb-engineering/building-a-faster-web-experience-with-the-posttask-scheduler-276b83454e91[2]scheduler。postTask:https://github.com/WICG/scheduling-apis/blob/main/explainers/prioritized-post-task.md[3]AbortSignalAPI:https://developer.mozilla.org/en-US/docs/Web/API/中止信号
