Skip to content

requestIdleCallback

题目

是否了解过 requestIdleCallback ?

由 React Fiber 引起的关注

React 16 内部使用 Fiber ,即组件渲染过程可以暂停,先去执行高优任务,CPU 闲置时再继续渲染。
其中用到的核心 API 就是 requestIdleCallback 。

requestAnimationFrame 每次渲染都执行,高优

页面的渲染是一帧一帧进行的,至少每秒 60 次(即 16.6ms 一次)才能肉眼感觉流畅。所以,网页动画也要这个帧率才能流畅。

用 JS 来控制时间是不靠谱的,因为 JS 执行本身还需要时间,而且 JS 和 DOM 渲染线程互斥。所以 ms 级别的时间会出现误差。
requestAnimationFrame 就解决了这个问题,浏览器每次渲染都会执行,不用自己计算时间。

代码参考 requestAnimationFrame.html

html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>requestAnimationFrame</title>
    <style>
        #box {
            width: 100px;
            height: 50px;
            border: 3px solid #333;
        }
    </style>
</head>
<body>
    <p>requestAnimationFrame</p>

    <button id="btn1">change</button>
    <div id="box"></div>

    <script>
        const box = document.getElementById('box')
        
        document.getElementById('btn1').addEventListener('click', () => {
            let curWidth = 100
            const maxWidth = 400

            function addWidth() {
                curWidth = curWidth + 3
                box.style.width = `${curWidth}px`
                if (curWidth < maxWidth) {
                    window.requestAnimationFrame(addWidth) // 时间不用自己控制
                }
            }
            addWidth()
        })
    </script>
</body>
</html>

requestIdleCallback 空闲时才执行,低优

requestIdleCallback 会在网页渲染完成后,CPU 空闲时执行,不一定每一帧都执行。

requestIdleCallback 不适合执行 DOM 操作,因为修改了 DOM 之后下一帧不一定会触发修改。

宏任务

requestAnimationFrame 和 requestIdleCallback 都是宏任务,它们比 setTimeout 更晚触发。

使用场景

requestAnimationFrame 可用于网页动画。

requestIdleCallback 可用于一些低优先级的场景,以代替 setTimeout 。例如发送统计数据。
但请注意 requestIdleCallback 的浏览器兼容性

答案

requestIdleCallback 可在网页渲染完成后,CPU 空闲时执行,用于低优先级的任务处理。