requestIdleCallback
浏览器提供的api工具
window.requestIdleCallback()
方法插入一个函数,这个函数将在浏览器空闲时期被调用。这使开发者能够在主事件循环上执行后台和低优先级工作,而不会影响延迟关键事件,如动画和输入响应。函数一般会按先进先调用的顺序执行,然而,如果回调函数指定了执行超时时间timeout
,则有可能为了在超时前执行函数而打乱执行顺序。
语法
requestIdleCallback(callback)
requestIdleCallback(callback, options)
参数
callback 必传
在一个事件循环空闲
interface IdleDeadline {
// 是否超时,如果任务规定了超时时间的话
readonly didTimeout: boolean;
// 给你的空闲时间,如果你的任务需要的时间超过这个时间,浏览器一样会卡顿
timeRemaining(): DOMHighResTimeStamp;
}
options (可选)
可选的配置参数。具有如下属性:
timeout:如果指定了 timeout,并且有一个正值,而回调在 timeout 毫秒过后还没有被调用,那么回调任务将放入事件循环中排队,即使这样做有可能对性能产生负面影响。这个时间跟上面的didTimeout息息相关。
返回值
一个 ID,可以把它传入 Window.cancelIdleCallback() 方法来结束回调。
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<script>
window.pageStartTime = Date.now();
</script>
<body>
<div id="box">这是一个渲染容器·</div>
</body>
<script>
// 模拟一个包含大量数据的数组
const largeDataSet = Array.from(
{ length: 100000 },
(_, index) => `Item ${index + 1}`
);
// 通过requestIdleCallback逐步渲染数据
const renderItems = (deadline) => {
while (
(deadline.timeRemaining() > 0 || deadline.didTimeout) &&
largeDataSet.length > 0
) {
const chunk = largeDataSet.splice(0, 10); // 每次处理10条数据
render(chunk); // 渲染这个数据块
}
if (largeDataSet.length > 0) {
requestIdleCallback(renderItems);
}
};
const render = (chunk) => {
chunk.map((i) => {
let p = document.createElement("p");
p.textContent = i;
document.getElementById("box").appendChild(p);
});
};
// 启动渲染
requestIdleCallback(renderItems); // 约为10
// render(largeDataSet); // 约为100
function load() {
window.firstScreen = Date.now();
}
load();
window.onload = function () {
// 首屏时间
console.log(window.firstScreen - window.pageStartTime);
};
</script>
</html>