requestidlecallback 是浏览器在主线程空闲时执行低优先级任务的调度 api,适用于日志上报、非关键资源预加载等可中断任务,需配合 timeout 和 deadline.timeremaining() 使用,并用 cancelidlecallback 取消。

requestIdleCallback 是什么,什么时候该用
requestIdleCallback 是浏览器提供的一个调度 API,用于在主线程空闲时执行低优先级任务。它不是定时器,也不保证执行时机,只承诺“如果接下来有空闲,就调用你”。适合做非紧急、可中断、不影响交互的任务,比如日志上报、预加载非关键资源、渐进式 DOM 渲染等。
别用它替代 setTimeout 或 requestAnimationFrame:前者要精确延时,后者要对齐帧率。用错场景会导致任务被无限推迟,甚至永不执行(比如页面一直有输入、滚动、动画)。
怎么正确注册和取消 requestIdleCallback
调用 requestIdleCallback 会返回一个 ID,必须用 cancelIdleCallback 取消,否则可能泄漏或重复执行:
const id = requestIdleCallback(doWork, { timeout: 2000 });
// ……中途决定不做了
cancelIdleCallback(id);
-
timeout参数很重要——没有它,空闲时间极短(比如用户刚抬起手指),回调可能根本没机会运行;设为2000表示“最多等 2 秒,不管空不空闲都执行” - 回调函数接收一个
deadline对象,必须用deadline.timeRemaining()判断还剩多少毫秒可用,不能硬写for (let i = 0; i - 如果任务超时未完成,应主动
return并在下一次回调中继续,deadline.didTimeout可帮你判断是否已超时
常见报错和兼容性坑
Chrome 47+、Edge 79+、Firefox 55+ 支持,Safari 一直没实现(截至 Safari 17.6)。直接调用会报 ReferenceError: requestIdleCallback is not defined。
- 必须做存在性检查:
if ('requestIdleCallback' in window),否则 SSR 或 Safari 下直接崩 - 某些安卓 WebView(如旧版 UC)虽有该函数,但
deadline.timeRemaining()恒为0,导致任务立即退出——建议加 fallback,比如降级为setTimeout(fn, 0) - 不要在
requestIdleCallback回调里再调requestIdleCallback形成链式调用,容易堆积任务或触发防抖机制被浏览器忽略
实际能跑通的最小示例
下面这段代码在支持的浏览器里能安全执行,并自动降级:
function runWhenIdle(task) {
if ('requestIdleCallback' in window) {
requestIdleCallback((deadline) => {
while (deadline.timeRemaining() > 0 && !deadline.didTimeout) {
task();
}
if (!deadline.didTimeout) {
requestIdleCallback(() => runWhenIdle(task));
}
}, { timeout: 1000 });
} else {
setTimeout(task, 0);
}
}
runWhenIdle(() => console.log('idle work'));
注意:这个模式只适合轻量、可拆分的任务;如果 task 本身是同步耗时操作(比如解析大 JSON),依然会卡住主线程——requestIdleCallback 不等于“不卡”,它只是给了你一个判断空闲的钩子。
真正难的是把业务逻辑拆成小块并维护状态,这点没人替你做。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











