Skip to content

requestAnimationFrame & requestIdleCallback

requestAnimationFrame

兼容IE10+

执行次数: 取决于显示器帧数, 例如:显示器60帧,则每秒执行60次

暂停时机: 后台标签页或者隐藏的 <iframe> 里时,该函数会被暂停调用以提升性能和电池寿命

返回值与停止: ①在循环调用的函数中做判断(常用); ②每一轮调用该函数会返回一个id(根据调用次数递增),调用cancelAnimationFrame(id);

参考文章

模仿setInterval

js
(() => {
  let startTime = Date.now()

  function handleTicker() {
    foo(Date.now() - startTime)
    startTime = Date.now()
    requestAnimationFrame(handleTicker)
  }

  requestAnimationFrame(handleTicker)

  let t = 0
  function foo(timeInterval) {
    t += timeInterval
    if (t > 1000) {
      console.log('在此实现setInterval中的逻辑')
      t = 0
    }
  }
})()

requestIdleCallback

一般显示器垂直刷新频率是60Hz,意味着浏览器每秒要绘制60张页面,即60帧。帧与帧的间隙可以称为时间片,长度为1000ms/60约等于16ms,如果一帧渲染完成的时间小于16ms,那么这个时间片内就有空闲时间

  • 空闲时间会被浏览器用来执行window.requestIdleCallback(callback)的回调函数

options(参数)

timeout: 表示超过这个时间后,如果任务还没执行,则强制执行,不必等待空闲。尚未通过超时毫秒数调用回调,那么回调会在下一次空闲时期被强制执行。如果明确在某段时间内执行回调,可以设置timeout值。在浏览器繁忙的时候,requestIdleCallback超时执行就和setTimeout效果一样

参数

参数1:callback 一个在事件循环空闲时即将被调用的函数的引用。函数会接收IdleDeadline参数,这个参数可以获取当前空闲时间以及回调是否在超时时间前已经执行的状态

IdleDeadline对象包含:

  • didTimeout,布尔值,表示任务是否超时,结合 timeRemaining 使用

  • timeRemaining(),表示当前帧剩余的时间,也可理解为留给任务的时间还有多少 (remaining: 剩余)

参数2:timeout,表示等待超时的时间,如果超过这个时间值还不执行callback函数,callback将会被强制执行

参考文章

参考文章2(经典)

返回值

和setTimeout、setInterval返回值一样, 可以传入cancelIdleCallback(id)取消执行

注意

js
function test(params) {
  // timeRemaining 表示当前帧剩余的时间,也可理解为留给任务的时间还有多少【一般最大为50】
  // 该回调会在params.timeRemaining() < 50 (空闲)时执行,不是等到onload与DOMcontentLoaded加载完才执行
  console.log(params.timeRemaining())
}

requestIdleCallback(test) 

window.addEventListener('load', () => console.log(1))

polifill

js
// 参考qiankun源码,空闲时间加载子应用
function requestIdleCallback(cb: CallableFunction) {
  const start = Date.now()
  return setTimeout(() => {
    cb({
      didTimeout: false,
      timeRemaining() {
        // 为什么是50?参考:https://juejin.cn/post/6844904196345430023#heading-4
        return Math.max(0, 50 - (Date.now() - start))
      }
    })
  }, 1)
}

优先级

requestAnimationFrame 的回调会在每一帧确定执行,属于高优先级任务.

requestIdleCallback 的回调则不一定,属于低优先级任务