tag

requestIdleCallback 实现闲时定时器

requestIdleCallback实现闲时定时器

如果你需要实现一个类似 idleTimeout(() => {}, 100) 的闲时定时器,即在浏览器空闲时执行任务,并且任务的执行时间间隔为 100ms,可以使用 requestIdleCallback 结合时间控制来实现。


实现思路

  1. 使用 requestIdleCallback

    • 在浏览器空闲时执行任务。
  2. 控制时间间隔

    • 使用一个变量记录上一次执行的时间,确保任务的执行间隔为 100ms。
  3. 重新安排任务

    • 在回调函数中重新调用 requestIdleCallback,确保任务能够持续执行。

实现代码

示例:

function idleTimeout(callback, delay) { let lastTime = Date.now(); // 记录上一次执行的时间 function idleTask(deadline) { const currentTime = Date.now(); const elapsedTime = currentTime - lastTime; // 计算时间间隔 // 如果时间间隔大于等于指定的延迟时间,执行回调函数 if (elapsedTime >= delay) { callback(); lastTime = currentTime; // 更新上一次执行的时间 } // 重新安排下一次执行 requestIdleCallback(idleTask); } // 注册空闲任务 requestIdleCallback(idleTask); } // 使用示例 idleTimeout(() => { console.log('Idle timeout callback executed at:', new Date().toLocaleTimeString()); }, 100); // 100ms 的延迟

解释

1. idleTimeout 函数

  • 参数

    • callback:需要执行的回调函数。
    • delay:指定的时间间隔(以毫秒为单位)。
  • 功能

    • 在浏览器空闲时执行回调函数,并确保执行间隔为 delay 毫秒。

2. lastTime

  • 记录上一次执行回调函数的时间。

3. elapsedTime

  • 计算当前时间与上一次执行时间的差值,表示时间间隔。
  • 如果 elapsedTime 大于等于 delay,则执行回调函数。

4. 重新安排任务

  • 在回调函数末尾,重新调用 requestIdleCallback(idleTask),确保任务能够持续执行。

示例效果

  • 当你调用 idleTimeout(() => {}, 100) 时,回调函数会在浏览器空闲时执行,并且每次执行的时间间隔为 100ms。
  • 如果浏览器一直繁忙,回调函数可能会延迟执行,但一旦浏览器空闲,任务会立即执行。

优化:结合 setTimeout

如果需要更精确的控制,可以结合 setTimeout 来实现。

示例:

function idleTimeout(callback, delay) { let lastTime = Date.now(); // 记录上一次执行的时间 function idleTask(deadline) { const currentTime = Date.now(); const elapsedTime = currentTime - lastTime; // 计算时间间隔 // 如果时间间隔大于等于指定的延迟时间,执行回调函数 if (elapsedTime >= delay) { callback(); lastTime = currentTime; // 更新上一次执行的时间 } // 重新安排下一次执行 if (deadline.timeRemaining() > 0) { requestIdleCallback(idleTask); } else { setTimeout(idleTask, 0); } } // 注册空闲任务 requestIdleCallback(idleTask); } // 使用示例 idleTimeout(() => { console.log('Idle timeout callback executed at:', new Date().toLocaleTimeString()); }, 100); // 100ms 的延迟

解释:

  1. deadline.timeRemaining()

    • 检查当前帧的剩余空闲时间。
    • 如果剩余时间大于 0,使用 requestIdleCallback 安排下一次执行。
    • 如果剩余时间不足,使用 setTimeout 安排下一次执行。
  2. setTimeout(idleTask, 0)

    • 如果浏览器繁忙,使用 setTimeout 来确保任务能够尽快执行。

总结

方案 适用场景 优点 缺点
idleTimeout 闲时定时器,指定时间间隔 在空闲时执行任务,节省资源 无法保证固定的时间间隔,时间间隔可能波动
idleTimeout + setTimeout 优化闲时定时器,结合两者的优点 在空闲时使用requestIdleCallback,繁忙时使用 setTimeout 实现稍微复杂,需要手动管理时间间隔

推荐:

  • 轻量级任务,空闲时执行:推荐使用 idleTimeout
  • 需要更精确的控制:推荐结合 idleTimeoutsetTimeout

结论

  • 你可以使用 requestIdleCallback 实现一个类似 idleTimeout(() => {}, 100) 的闲时定时器。
  • 通过控制时间间隔,确保任务在浏览器空闲时执行,并且每次执行的时间间隔为指定的毫秒数。
  • 如果需要更精确的控制,可以结合 setTimeout 来优化实现。
image.png

留下你的脚步
推荐阅读