浏览器的页面都是通过引擎一帧一帧绘制出来的,当每秒绘制的帧数达到 60 的时候,页面就是流畅的,玩过 fps 游戏的都知道,当这个帧数小于 60 的时候,人的肉眼就能感知出来卡顿。一秒 60 帧,每一帧分到的时间就是 1000/60 ≈ 16 ms,如果每一帧执行的时间小于 16 ms,就说明浏览器有空余时间,那么能不能通过浏览器的空余时间去处理任务呢,这样就不用一直等待主任务执行完了,requestIdleCallback
就是利用浏览器的空余时间去执行任务的。
window.requestIdleCallback()
方法将在浏览器的空闲时段内调用的函数排队。这使开发者能够在主事件循环上执行后台和低优先级工作,而不会影响延迟关键事件,如动画和输入响应。函数一般会按先进先调用的顺序执行,然而,如果回调函数指定了执行超时时间timeout,则有可能为了在超时前执行函数而打乱执行顺序。
代码解释
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>My Website</title>
<link rel="stylesheet" href="./style.css">
<link rel="icon" href="./favicon.ico" type="image/x-icon">
<style>
#box {
padding: 20px;
background: palegoldenrod;
}
</style>
</head>
<body>
<div id="box"></div>
<button id="btn1">执行计算任务</button>
<button id="btn2">更改背景颜色</button>
<script>
const box = document.getElementById('box')
const btn1 = document.getElementById('btn1')
const btn2 = document.getElementById('btn2')
let number = 9999
let value = 0
function calc() {
while (number > 0) {
value = Math.random() < 0.5 ? Math.random() : Math.random()
console.log(value)
number--
}
}
btn1.onclick = function () {
calc()
}
btn2.onclick = function () {
box.style.background = 'green'
}
</script>
<script src="index.js"></script>
</body>
</html>
上面的代码,我们通过一个很长的循环创建随机数,增加浏览器的计算量,你可以通过本地的 ide 试试这个 demo,就会发现当你点击 执行计算任务 后,再点击 更改背景颜色 按钮后,box 的颜色不会立马改变,而是会等待几秒后才发生改变(如果电脑性能差,可能会更慢)。这时因为 native GUI 和 v8引擎的渲染是互斥的,所以页面渲染会有一些延迟。
<style>
#box {
padding: 20px;
background: palegoldenrod;
}
</style>
<!-- body -->
<div id="box"></div>
<button id="btn1">执行计算任务</button>
<button id="btn2">更改背景颜色</button>
<script>
const box = document.getElementById('box')
const btn1 = document.getElementById('btn1')
const btn2 = document.getElementById('btn2')
let number = 999999
let value = 0
function calc(deadline) {
while (number > 0 && deadline.timeRemaining() > 0) {
value = Math.random() < 0.5 ? Math.random() : Math.random()
console.log(value)
number--
}
requestIdleCallback(calc)
}
btn1.onclick = function () {
requestIdleCallback(calc)
}
btn2.onclick = function () {
box.style.background = 'green'
}
</script>
上面的代码是使用了 requestIdleCallback
去优化的,运行之后,在点击 更改背景颜色 的按钮后,立马就能看到颜色的变化,这就是 requestIdleCallback
的作用。