为了提高浏览器的性能和用户体验,现代浏览器采用了一些技术来优化主线程的执行。本文将提供浏览器因JS耗时任务导致页面卡顿的部分解决方案。主要着重讲解requestIdleCallback
(RIC)和requestAnimationFrame
(RAF)。
setTimeout
延迟加载 (使用不当可能适得其反)web worker
多线程 (不能操作dom,主要计算密集型的任务)requestIdleCallback
帧空闲时运行 (react18带🔥的,低优先级任务)requestAnimationFrame
每帧都会运行 (主要做动画效果调优)
在进入正题之前我们有必要先了解一下帧与卡顿。
帧 |
在计算机图形和动画领域,帧(Frame)是指一幅静态图像或一帧图像。当这些帧以一定的速率连续播放时,就会形成动画或视频的效果。
帧率 |
在动画或视频中,帧率(frame rate)表示每秒渲染的图像帧数。人眼对于连续视觉变化的感知能力通常被认为是每秒24到30帧。这意味着当连续的静态图像以每秒24到30帧的速度在屏幕上播放时,人眼会感知到流畅的运动和连续的动画效果。较高的帧率可以提供更流畅的动画效果,使用户感觉到连贯和真实的运动。当帧率高于30帧时,人眼对于连续动画的感知能力有所限制,因此超过这个帧率对大多数人来说没有明显的区别。
卡顿 |
浏览器的主线程是一个单线程,负责处理页面渲染、用户交互和执行 JavaScript 代码的线程。它按照任务队列(task queue)中的顺序依次执行任务(FIFO)。当任务被添加到任务队列中时,主线程会处理当前的任务,然后再处理下一个任务。
如果一个任务执行时间过长,它会阻塞主线程对页面的渲染,导致页面变得卡顿或不响应。
浏览器中的一帧 |
图片来源:the-anatomy-of-a-frame
暂不展开讲解,后续有时间将单独写一文章。流水线流程可参看我之前文章:页面的渲染流程(Chrome)
浏览器帧率和显示器帧率 |
显示器的帧率(也称为刷新率)是指显示器每秒钟刷新屏幕的次数。它通常以赫兹(Hz)为单位表示,例如60 Hz、120 Hz或144 Hz。显示器的帧率决定了它能够显示的最大帧数。
浏览器帧率是指在网页浏览器中渲染和显示网页内容的帧率。它表示浏览器每秒钟更新屏幕上的内容的次数。尽管60帧/秒是一种常见的标准,但浏览器的帧率并不仅限于60帧/秒,并且可能根据不同的环境和设备而有所变化。
浏览器帧率可以受多个因素影响,包括浏览器的性能、网页的复杂程度、脚本和动画效果的使用等。浏览器的帧率可以根据设备的硬件性能、操作系统的设置和显示器的刷新率进行调整和适配。
|
一个耗时任务的示例:
<!DOCTYPE html>
<html>
<body>
<span>js耗时任务测试</span>
<script>
// 计算任务耗时毫秒数
function processTaskTime(callback, ...args) {
const startTime = new Date().valueOf();
callback(...args);
let endTime = new Date().valueOf();
const processTime = endTime - startTime;
console.log(`%c 执行 ${
callback.name}(${
args}) 消耗时间:` + processTime + '毫秒', 'color:green')
return processTime;
}
// 双重遍历,计算求和 耗时任务
function sumLoop(start, end) {
let sum = 0
for (let i = start; i < end; i++) {
for (let j = start; j < end; j++) {
tmp = sum;
sum = tmp + i + j
}
}
console.log(`从${
start}到${
end}自相相加和为:` + sum)
return sum
}
processTaskTime(sumLoop, 0, 15000)
</script>
<button onclick="processTaskTime(sumLoop,0,15000)"> 执行耗时任务 </button>
<button onclick="javascript:console.log('click event')"> click </button>
</body>
</html>
刷新看下页面的运行效果:
刷新页面我们可以看到,页面加载了一小会才加载出来,因为processTaskTime(sumLoop, 0, 15000)
的执行就消耗了3000多毫秒(与个人电脑当时运行配置有关)。这对用户而言可谓相当的不友好,对网站自身而言也不利于SEO。是否有改进的方式呢?
✿ 进一步观察 ,按下 执行耗时任务
按钮,立刻按下 click
按钮,为啥没有第一时间触发 click
按钮事件呢?
⭐ 触发的事件,都会依次加入到事件队列,先进先出,依次执行。
|
1️⃣有法子让首屏加载