tk挠痒痒网址发布页-秘密武器
历史搜索

window.reqeustIdleCallback方法详解

游客2025-05-16 12:46:01
目录文章目录
  1. 定义和用法
  2. reqeustIdleCallback 的执行行为
  3. 最长执行时间
  4. 使用建议
  5. React 如何 polyfill

它和 requestAnimationFrame 一样吗?
最初我以为这个函数就是和实现动画的 requestAnimationFrame 拥有相同的行为,因为它们的使用方法非常类似,但实际使用后发现它们的差别还是蛮大的。本文主要对这个神秘的函数进行一些说明和分析。

关于 requestAnimationFrame 相关内容看我之前文章《JavaScript 中 requestAnimationFrame 函数的简单介绍 用以实现流畅的动画》、《将 requestAnimationFrame 与 React Hooks 一起使用

定义和用法

首先来看一下它的定义和用法,MDN 是这样定义它的:

这是一个实验中的功能,window.requestIdleCallback() 将一个(即将)在浏览器空闲时间执行的函数加入队列,这使得开发者在主事件循环中可以执行低优先级工作,而不影响对延迟敏感的事件,如动画和输入响应。

通过这个定义,我们发现它的执行时机在浏览器的“空闲”状态,那么怎样定义这个状态呢?

浏览器每一帧都需要完成这些任务:

  1. 处理用户交互
  2. JS 执行
  3. 一帧的开始,处理视窗变化、页面滚动等
  4. requestAnimationFrame(rAF)
  5. 重排(layout)
  6. 绘制(draw)

在这些步骤完成后,如果时间消耗还没超过 16ms,则浏览器还有余力去处理其他的任务,我们在 reqeustIdleCallback 中传入的回调将在此时执行;相反,如果时间消耗太大,则回调不执行,任务会顺延到下个帧浏览器空闲的时候再执行。而如果浏览器一直都很忙,那任务就会一再被推迟,很可能需要消耗大量时间后才得到执行。为了解决这个问题,可以在注册任务的时候提供一个 timeout 参数指定超时时间,在超时时间之内,该任务会被优先放在浏览器的执行队列中。

下面来看下它的用法:

// 这些只为了表明一些参数定义
type Dealine = {
  timeRemaining: () => number // 当前剩余的可用时间
  didTimeout: boolean // 是否超时
}
type Tick = (deadline: Dealine) => void;
type Options = { timeout: number }; // 可以提供一个超时时间,配合上面的 didTimeout 一起用
type RequestIdleCallback = (tick: Tick, options?: Options) => number // 类似于 rAF 返回一个句柄,可以把它传入 cancelIdleCallback 取消掉任务

一个常见的用法是,当有剩余时间或者 timeout 发生时执行一些任务,通常将任务保存在一个队列中便于进行调度。

// 待执行的任务队列
const taskQueue = [];

const tick = function(deadline) {
  const remaining = deadline.timeRemaining();
  while (remaining > 0 || didTimeout) {
    // 如果超时,或者还有剩余执行时间,则执行这里的任务
    // 执行任务队列中的任务
    const currentTask = taskQueue.shift();
    exec(currentTask);
  }
  // 再次注册,在下一个间隙继续执行 taskQueue 中的任务
  requestIdleCallback(tick, { timeout: 500 });
};

requestIdleCallback(tick, { timeout: 500 });

reqeustIdleCallback 的执行行为

requestAnimationFrame 大家经常拿来实现动画,因为它是一个“靠谱的”函数,如果页面没有阻塞,那么这个函数每 16ms 左右调用一次;requestIdleCallback 则不同,它的执行间隔是不固定的,取决于浏览器此时正在执行的任务,下面举几个例子来看下。

我们简单地在页面中注册 requestIdleCallback,先不提供 timeout 参数

const tick = function(deadline) {
  const remaining = deadline.timeRemaining();
  if (remaining > 0) {
    // do some stuff
  }
  requestIdleCallback(tick);
};

requestIdleCallback(tick);

场景一,页面中同时使用 requestAnimationFrame 函数循环注册一个事件,使页面发生重绘。

const cutiePie = document.querySelector('.cutie-pie');
const t = () => {
  cutiePie.style.transform = `translate(${1 - Math.random() * 100}px, 0)`;
  requestAnimationFrame(t);
}
requestAnimationFrame(t);

window.reqeustIdleCallback方法详解 1

以上就是 window.reqeustIdleCallback 方法详解的详细内容,更多请关注www.mimiwuqi.com的其它相关文章!

标签:JavaScript

本文是由用户"游客"发布,所有内容的版权归原作者所有。没有经过书面许可,任何单位或个人不得以任何形式复制、转载、引用本网站的内容。否则将追究法律责任。

相关专题