首页 > 其他分享 >js requestIdleCallback使用,避免阻塞主线程页面主要js执行

js requestIdleCallback使用,避免阻塞主线程页面主要js执行

时间:2024-12-19 20:41:42浏览次数:3  
标签:执行 函数 idleCallbackId js requestIdleCallback 回调 cancelIdleCallback 页面

requestIdleCallback 是一个浏览器提供的 API,用于在主线程空闲时执行低优先级的操作,而不会阻塞主线程的执行。这对于执行一些非紧急的任务(如统计、数据预处理等)非常有用。

以下是 requestIdleCallback 的基本使用方法:

  1. 定义一个回调函数:这个函数将在主线程空闲时执行。
  2. 调用 requestIdleCallback 并传入回调函数:这个方法会返回一个唯一的 ID,用于后续的取消操作。
  3. (可选)使用 cancelIdleCallback 取消回调:如果需要取消已经排期的回调,可以使用这个方法。

示例代码

// 定义一个回调函数
function myIdleTask(deadline) {
    // 检查是否有剩余时间
    while ((deadline.timeRemaining() > 0 || deadline.didTimeout) && tasks.length > 0) {
        doOneTask();
    }

    // 如果还有任务未完成,继续请求空闲时间
    if (tasks.length > 0) {
        requestIdleCallback(myIdleTask);
    }
}

// 调用 requestIdleCallback 并传入回调函数
let idleCallbackId = requestIdleCallback(myIdleTask);

// 取消回调(可选)
cancelIdleCallback(idleCallbackId);

参数说明

  • 回调函数:接受一个 deadline 参数,该参数是一个对象,包含两个属性:

    • timeRemaining():返回当前帧还剩多少时间(毫秒)。
    • didTimeout:一个布尔值,表示是否因为超时执行了回调。
  • options(可选):可以传入一个配置对象,包含一个 timeout 属性,表示回调函数的最大等待时间(毫秒)。如果设置了 timeout,即使主线程没有空闲时间,回调函数也会在超时后执行。

注意事项

  • requestIdleCallback 在某些浏览器中可能不可用,因此建议使用 polyfill 以确保兼容性。
  • 使用 requestIdleCallback 时,不要依赖它来执行关键任务,因为它可能会在主线程非常繁忙时被推迟执行。

Polyfill

如果需要兼容不支持 requestIdleCallback 的浏览器,可以使用以下 polyfill:

if (!window.requestIdleCallback) {
    window.requestIdleCallback = function (callback, options) {
        const { timeout } = options || {};
        const startTime = Date.now();

        return setTimeout(function () {
            callback({
                timeRemaining: function () {
                    return Math.max(0, timeout - (Date.now() - startTime));
                },
                didTimeout: Boolean(timeout) && Date.now() - startTime >= timeout
            });
        }, 1);
    };
}

if (!window.cancelIdleCallback) {
    window.cancelIdleCallback = function (id) {
        clearTimeout(id);
    };
}

通过这种方式,你可以确保 requestIdleCallback 在所有浏览器中都能正常工作。

对于单页引用可能需要手动关闭requestIdleCallback

requestIdleCallback 本身不会自动关闭或取消已经排期的回调。如果你不再需要执行某个回调,或者组件被卸载了,你需要手动取消该回调。这可以通过 cancelIdleCallback 方法来实现。

以下是一个示例,展示了如何在组件卸载时取消 requestIdleCallback

import { onMounted, onUnmounted, ref } from 'vue';

export default {
  setup() {
    const idleCallbackId = ref(null);

    function idleTask(deadline) {
      // 执行一些任务...
      console.log('Executing idle task');

      // 如果需要继续执行任务,可以再次请求空闲时间
      idleCallbackId.value = requestIdleCallback(idleTask);
    }

    onMounted(() => {
      // 组件挂载时请求空闲时间
      idleCallbackId.value = requestIdleCallback(idleTask);
    });

    onUnmounted(() => {
      // 组件卸载时取消空闲回调
      if (idleCallbackId.value !== null) {
        cancelIdleCallback(idleCallbackId.value);
      }
    });

    return {
      idleCallbackId
    };
  }
};

在这个示例中,idleCallbackId 保存了 requestIdleCallback 返回的 ID。当组件卸载时,通过 cancelIdleCallback 取消回调,以防止组件卸载后仍然执行回调函数。

总结

虽然 requestIdleCallback 不会自动关闭,但在某些情况下(如组件卸载、任务完成等),你需要手动取消回调,以避免不必要的执行和可能的内存泄漏。使用 cancelIdleCallback 可以轻松实现这一点。

如果被执行过的requestIdleCallback,不需要手动关闭

requestIdleCallback 的回调函数在执行完毕后,如果没有再次调用 requestIdleCallback 来安排下一次执行,那么它就不需要被关闭。换句话说,当 requestIdleCallback 的回调函数执行完毕后,它自然就结束了,不需要额外的关闭操作。

但是,如果你在回调函数内部再次调用了 requestIdleCallback 来安排下一次执行,那么你需要确保在适当的时候(例如组件卸载或任务完成时)使用 cancelIdleCallback 来取消未来的回调。

示例

以下是一个示例,展示了如何根据任务列表来决定是否需要再次调用 requestIdleCallback

// 定义一个任务列表
const tasks = [
  () => console.log('Task 1 completed'),
  () => console.log('Task 2 completed'),
  () => console.log('Task 3 completed'),
  // 添加更多任务...
];

// 定义一个回调函数,用于在空闲时间执行任务
function idleTask(deadline) {
  // 检查是否有剩余时间
  while ((deadline.timeRemaining() > 0 || deadline.didTimeout) && tasks.length > 0) {
    // 执行任务
    const task = tasks.shift();
    task();
  }

  // 如果还有任务未完成,继续请求空闲时间
  if (tasks.length > 0) {
    requestIdleCallback(idleTask);
  }
}

// 请求空闲时间并传入回调函数
requestIdleCallback(idleTask);

在这个示例中,idleTask 回调函数会在每次执行时检查任务列表。如果任务列表中还有任务,它会再次调用 requestIdleCallback 来安排下一次执行。如果任务列表为空,回调函数自然结束,不需要额外的关闭操作。

总结

  • 不需要关闭:如果 requestIdleCallback 的回调函数执行完毕后没有再次调用 requestIdleCallback,那么它就不需要被关闭。
  • 需要关闭:如果在回调函数内部再次调用了 requestIdleCallback,那么在适当的时候(如组件卸载或任务完成时)需要使用 cancelIdleCallback 来取消未来的回调。

标签:执行,函数,idleCallbackId,js,requestIdleCallback,回调,cancelIdleCallback,页面
From: https://www.cnblogs.com/jocongmin/p/18617896

相关文章

  • Jackson的@JsonGetter 注解
    1.概述Jackson是Java生态系统中不可或缺的工具,提供了将Java对象序列化为JSON以及反序列化的功能。它的一个特性是@JsonGetter注解,用于在序列化过程中自定义getter方法输出的名字。@JsonGetter注解概览Jackson的@JsonGetter注解用来标识一个方法作为特定属......
  • Jackson 的@JsonAnyGetter注解
    1.概述在Java领域,Jackson是一个非常灵活的库,用于将Java对象转换为JSON格式,并支持反向操作。它的一个强大注解是@JsonAnyGetter,该注解允许在序列化的JSON中添加动态属性,而无需在POJO(PlainOldJavaObject)中定义具体的属性。@JsonAnyGetter注解概览@JsonAnyGe......
  • 修改python jsonpickle源码, 实现不序列化对象私有成员(2)
    在前一篇文章中,通过修改源码来实现对象的私有成员不被序列化的功能.但是不够灵活,于是我又修改了一版,能够自定义过滤函数.实现起来不是很难,要点如下:#pickler.py的_flatten_obj_instance函数self._current_obj=obj#记录正在处理的对象returnself._flatten_dict......
  • 大文件传输与断点续传实现(极简Demo: React+Node.js)
    大文件传输与断点续传实现(极简Demo:React+Node.js)简述使用React前端和Node.js后端实现大文件传输和断点续传的功能。通过分片上传技术,可以有效地解决网络不稳定带来的传输中断问题。文章内容前端实现(React)首先,您需要在前端项目中安装axios、spark-md5库以处理HTTP请求。可以......
  • node.js毕设德云社票务系统程序+论文
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容一、选题背景关于票务系统的研究,现有研究主要以大型综合票务平台为主,专门针对德云社这种特定文化娱乐场景下的票务系统研究较少。因此本选题将以德云社票务为研究情......
  • node.js毕设地铁舆情管理系统程序+论文
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容一、选题背景关于地铁舆情管理系统的研究,现有研究多集中在舆情管理的通用理论和大型交通系统的舆情监控上,专门针对地铁这一特定交通场景的舆情管理系统的研究较少。......
  • egg.js 使用 wechatpay-node-v3 微信支付
    安装$npmiwechatpay-node-v3--save创建controller/wx.js文件asyncwxPay(){ //把配置常量放在了/config/config.js中const{config,ctx}=thisconst{openId}=ctx.queryconstpay=newWxPay({appid:config.wx.appid,mchid:con......
  • 前端播放AE动画库 bodymovin.js的一些使用方法
    加载动画varanimData={wrapper:$("#ae_privewdiv")[0],animType:'svg',loop:true,prerender:true,autoplay:true,path:src,};letanim=bodymovin.loadAnimation(animData); 一、获取动画总帧数、帧率、时长//true为获取总帧数anim.......
  • React的使用笔记1 React 项目的创建与JSX基础知识
    时间久远,工作中没有遇到react的情况,早就忘记React怎么写了~回顾一下吧。React项目的搭建npxcreat-react-appapp-nameReact项目的运行具体可以参考README中的说明,没有特殊的情况下,直接npmstart删除项目src目录中不必要的代码先,仅保留入口文件即可,即App.js与index.j......
  • EasyPlayer.js视频流媒体播放器在React项目中应如何使用?
    H5流媒体播放器,作为基于HTML5技术的创新产品,近年来在音频和视频播放领域取得了显著的发展。它不仅为用户提供了流畅、稳定的播放体验,还通过丰富的交互功能增强了用户的参与感。那么在实际应用时,在React项目中应如何使用EasyPlayer播放器呢?1、在官网下载播放器压缩包。2、解压......