优化浏览器主线程执行的几个API,着重讲解 requestIdleCallback 与 requestAnimationFrame

为了提高浏览器的性能和用户体验,现代浏览器采用了一些技术来优化主线程的执行。本文将提供浏览器因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 按钮事件呢?

请添加图片描述

⭐ 触发的事件,都会依次加入到事件队列,先进先出,依次执行。

setTimeout

1️⃣有法子让首屏加载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值