当前位置: 首页 > Web前端 > vue.js

postTask:React的杀手级特性是浏览器原生实现的?

时间:2023-04-01 00:21:13 vue.js

大家好,我是Kason。React这几年一直在完善的并发模型主要由以下两部分组成:基于纤程实现的可中断更新架构基于Scheduler的优先级调度可以说从2016年到年底,纤程架构一直在重构今年(或明年)年初的React18发布了正式版。这期间,React团队的大部分工作都是围绕这两点展开的。如果我现在告诉你,浏览器原生支持React多年来实现的优先级调度,你会感到惊讶吗?这篇文章指的是使用postTaskScheduler构建更快的Web体验。什么是优先级调度假设我们有一个日志脚本需要在页面初始化后执行:initCriticalTracking();调用栈torch图如下:可以看到,这是一个执行了249.08ms的长任务。在执行过程中,浏览器Frames会被丢弃(表示为:浏览器冻结)。现在,我们将其包装在优先级调度函数scheduler.postTask的回调函数中:scheduler.postTask(()=>initCriticalTracking());长任务分解为多个短任务:每个任务之间浏览器有机会重排、重绘,减少掉帧的机会。这种根据任务的优先级分解任务并分配执行时间的技术称为优先级调度。scheduler.postTask是Chrome实现的优先级调度API。scheduler.postTask是一个实验性的功能,需要在chrome://flags中开启#enable-experimental-web-platform-features如何在scheduler.postTask出现之前实现优先级调度,通常使用浏览器提供不同的API中调用stage模拟优先级调度,例如:requestAnimationFrame(简称rAF)一般用于处理动画,会在浏览器渲染前触发requestIdleCallback(简称rIC)。在没有其他任务时,在每帧空闲时间调用setTimeout、postMessage、MessageChannel在renders间触发React,使用MessageChannel进行优先级调度,setTimeout作为fallback方案。不过这些API毕竟各有各的工作。用他们实现的优先级调度比较粗糙。为此,postTaskScheduler诞生了。postTaskScheduler使用scheduler.postTask有3个可选的优先级:优先级描述polyfill实现用户阻塞的最高优先级,可能会阻塞用户交互。使用MessageChannel调度任务,setTimeout是第二优先级用户可见的降级方案。对用户可见,但不阻止用户交互。例如:渲染副屏内容。这是基于用户阻塞的实现,通过优先级队列控制后台最低优先级的默认优先级。通常,执行非紧急任务,例如使用rIC进行日志记录。setTimeout(0)作为降级解决方案使用起来非常简单,通过以下方式注册的回调函数将以默认优先级进行调度://默认优先级scheduler.postTask(()=>console.log('Hello,postTask'));您还可以指定优先级和执行延迟://调用延迟1秒后,最低优先级scheduler.postTask(()=>console.log('Hello,postTask'),{delay:1000,priority:'背景',});postTask是建立在AbortSignalAPI之上的,所以我们可以取消那些还在排队还没有执行的回调函数。通过使用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现在正在做的吗?欢迎加入人类优质前端框架研究组,带头