无需登录 数据私有 本地保存

requestIdleCallback 任务调度演示 - 空闲时间利用

11
0
0
0
任务调度控制台
自定义
超时设置:
当前状态
空闲中
空闲率
98%
过去15秒
已完成任务
0
共执行
队列等待
0
待处理任务
主线程时间线(最近15秒)
空闲 繁忙 任务执行
执行日志
时间 任务名称 耗时 剩余时间 状态
暂无日志,添加任务开始观察
常见问题 & 知识点

requestIdleCallback 是浏览器提供的一个API,允许开发者在浏览器空闲时段执行低优先级的后台任务。它的核心价值在于:让非关键任务为主线程的关键渲染工作让路,从而提升用户体验。

典型使用场景包括:数据上报、预加载资源、日志写入、分析计算、缓存清理等不需要立即完成的工作。

回调函数会收到一个 IdleDeadline 对象,提供 timeRemaining() 方法(返回当前空闲时段剩余毫秒数)和 didTimeout 属性。

  • requestAnimationFrame (rAF):在每帧渲染之前执行,适合视觉更新(动画、DOM修改),保证与屏幕刷新率同步,优先级高。
  • requestIdleCallback (rIC):在浏览器空闲时执行,适合非视觉后台任务,优先级低,不保证执行时机。
  • 简单记忆:rAF面向渲染,rIC面向空闲。动画用rAF,数据上报用rIC。
  • rAF 每帧都会触发(约16ms一次),rIC 可能数秒才触发一次(取决于主线程繁忙程度)。

deadline.timeRemaining()返回当前空闲时段还剩余多少毫秒。开发者应在此时间内完成工作。通常初始值约50ms,但可能更少。如果时间快用完,应将任务暂停并重新调度。

deadline.didTimeout布尔值。如果因为设置了 timeout 且超时触发而强制执行回调,则为 true。此时即使 timeRemaining() 为0也应执行任务,以保证任务不会无限期延迟。

最佳实践:先检查 didTimeout,如果为true则必须执行;否则根据 timeRemaining() 决定执行多少工作。

支持情况:Chrome 47+、Edge 79+、Firefox 55+、Opera 34+、Android Chrome 47+。Safari 目前不支持(截至2024年)。

降级方案(Polyfill):

window.requestIdleCallback = window.requestIdleCallback || function(cb, options) {
  var start = Date.now();
  return setTimeout(function() {
    cb({
      didTimeout: false,
      timeRemaining: function() { return Math.max(0, 50 - (Date.now() - start)); }
    });
  }, options && options.timeout ? options.timeout : 1);
};

降级到 setTimeout 虽然失去了真正的空闲感知能力,但能保证代码不报错。

  1. 拆分大任务:将大任务拆成小块,每次只执行 timeRemaining() 允许的工作量。
  2. 设置合理的timeout:对于不能无限延迟的任务,设置超时保证最终执行。
  3. 避免DOM操作:idle callback中修改DOM可能导致强制重排,建议只做纯计算或数据操作。
  4. 不要在idle callback中再次调度rIC:避免无限循环,确保有退出条件。
  5. 检查didTimeout:超时触发时应完成必要工作,即使时间不足。
  6. 监控任务执行:记录任务执行情况,便于性能分析和调试。

适合低优先级、可延迟、非UI相关的任务:

  • 📊 埋点数据上报、用户行为日志发送
  • 📦 预加载下一页资源、预取数据
  • 💾 本地存储清理、缓存维护
  • 🔍 搜索索引构建、数据同步
  • 📝 草稿自动保存(需设置timeout)
  • 🤖 AI/ML推理(非实时场景)