什么是requestIdleCallback?和requestAnimationFrame有什么区别?

什么是requestIdleCallback?

我们都知道React 16实现了新的调度策略(Fiber), 新的调度策略提到的异步、可中断,其实就是基于浏览器的 requestIdleCallback和requestAnimationFrame两个API。


在 JavaScript 中,requestIdleCallback 是一个用于执行回调函数的 API,该回调函数会在浏览器空闲时执行,而不会影响页面的性能和用户体验。它的作用是在浏览器的空闲时段执行任务,以确保这些任务不会阻塞主线程,从而提高页面的响应性。

具体来说,requestIdleCallback 可以用于执行一些不那么紧急的任务,比如:

  1. 执行复杂的计算: 如果有一些需要较长时间才能完成的计算任务,可以使用 requestIdleCallback 将其放在空闲时执行,而不会阻塞用户与页面的交互。

  2. 后台数据同步: 可以在空闲时检查是否有需要同步的数据,并进行相应的后台同步操作。

  3. 图片懒加载: 对于页面上一些不太重要的图片,可以在空闲时加载,而不影响首屏渲染。

下面是一个简单的示例:

// 在空闲时执行任务
requestIdleCallback(function (deadline) {
    
    
  while (deadline.timeRemaining() > 0) {
    
    
    // 执行一些任务
    // ...
  }
});

deadline 是一个对象,用于提供当前帧的一些信息,而 deadline.timeRemaining() 是一个函数,用于获取当前帧还剩余的时间。

具体来说,deadline.timeRemaining() 返回一个表示当前帧剩余时间的毫秒数。在回调函数执行期间,可以多次调用这个函数,以检查当前帧是否还有足够的时间来执行任务。


requestIdleCallback 的第二个参数是一个 options 对象,用于配置回调函数的行为。这个对象有以下属性:

  1. timeout (可选): 用于指定回调函数执行的最大时间。如果在指定的时间内回调函数没有完成,它仍然会在空闲时执行,但是会提前终止。这可以用来确保回调函数在有限的时间内完成,以避免长时间运行的任务影响用户体验。这个值是一个毫秒数。
requestIdleCallback(
  function (deadline) {
    
    
    // 执行任务
  },
  {
    
     timeout: 1000 } // 设置最大执行时间为 1000 毫秒
);
  1. signal (可选): 这是一个 AbortSignal 对象,可以用来取消回调函数的执行。当传递了这个参数时,如果 AbortSignal 被触发,回调函数会被取消。
const controller = new AbortController();
const signal = controller.signal;

// 启动回调函数
requestIdleCallback(
  function (deadline) {
    
    
    // 执行任务
  },
  {
    
     signal }
);

// 在需要的时候取消
controller.abort();

这两个参数提供了对回调函数执行的一些控制和限制。在实际使用时,可以根据任务的性质和需求进行配置。

需要注意的是,requestIdleCallback 并不是所有浏览器都支持的标准 API,可能需要进行兼容性处理。另外,由于浏览器对空闲时段的定义可能不同,因此在实际使用时,应该根据具体情况进行测试和调整。最新的浏览器也提供了 requestAnimationFramerequestAnimationFrame 方法来执行类似的任务。

requestAnimationFrame和requestIdleCallback是宏任务还是微任务?

大家都知道异步任务分为宏任务和微任务,要搞清楚 requestAnimationFrame requestIdleCallback 是宏任务还是微任务就必须要搞清楚下面几个问题:

  • 浏览器在每一轮Event Loop事件循环中都会去渲染屏幕吗?
  • requestAnimationFrame在哪个阶段执行,是在渲染前还是渲染后?是在微任务执行前还是执行后?
  • requestIdleCallback在哪个阶段执行,是在渲染前还是渲染后?是在微任务执行前还是执行后?
console.log(22)
requestIdleCallback(()=>{
    
    
    console.log(11)
})

console.log(33)
requestAnimationFrame(()=>{
    
    
    console.log("动画")
})

在这里插入图片描述


requestAnimationFrame和requestIdleCallback是和宏任务性质一样的任务,只是他们的执行时机不同而已。也有人说它们既不是宏任务也不是微任务,其实我们不必纠结这个,我们所要做的就是知道他们的执行时机就好。
浏览器在每一轮Event Loop事件循环中不一定会去重新渲染屏幕,会根据浏览器刷新率以及页面性能或是否后台运行等因素判断的,浏览器的每一帧是比较固定的,会尽量保持60Hz的刷新率运行,每一帧中间可能会进行多轮事件循环。

  • requestAnimationFrame回调的执行与task和microtask无关,而是与浏览器是否渲染相关联的。它是在浏览器渲染前,在微任务执行后执行。
  • requestIdleCallback是在浏览器渲染后有空闲时间时执行,如果requestIdleCallback设置了第二个参数timeout,则会在超时后的下一帧强制执行。

猜你喜欢

转载自blog.csdn.net/m0_46672781/article/details/134688044