React Fiber 使用 MessageChannel + requestAnimationFrame 模拟实现 requestIdleCallback

news2024/11/26 16:46:35

由于 requestIdleCallback 兼容性较差且不支持 Safari,React Fiber 需要实现一个 requestIdleCallback polyfill 做浏览器兼容;

  • MDN RequestIdleCallback
  • MDN RequestAnimationFrame
  • MDN MessageChannel

以下为其使用 MessageChannel + requestAnimationFrame 实现 requestIdleCallback

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
    />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <script>
      // 休眠函数
      const sleep = (delay) => {
        let startTime = Date.now();
        while (delay + startTime > Date.now()) {}
      };

      // 任务列表
      let works = [
        () => {
          console.log("任务 1 开始");
          sleep(20);
          console.log("任务 1 结束");
        },
        () => {
          console.log("任务 2 开始");
          sleep(20);
          console.log("任务 2 结束");
        },
        () => {
          console.log("任务 3 开始");
          sleep(20);
          console.log("任务 3 结束");
        },
        () => {
          console.log("任务 4 开始");
          sleep(20);
          console.log("任务 4 结束");
        },
        () => {
          console.log("任务 5 开始");
          sleep(20);
          console.log("任务 5 结束");
        },
      ];

      const { port1, port2 } = new MessageChannel();

      const activeTimeFrame = 1000 / 60; // 帧率
      let deadFrameTime; // 每一帧的结束时间
      let pendingCallback; // requestIdleCallback的回调
      let timeRemaining = () => deadFrameTime - performance.now(); // 剩余时间

      window.requestIdleCallback = function (callback, option) {
        window.requestAnimationFrame(function (rafTime) {
          // resTime 表示 每一帧开始时间
          pendingCallback = callback;
          // 每一帧的结束时间(开始时间 + 执行时间 = 结束时间)
          deadFrameTime = rafTime + activeTimeFrame;
          port1.postMessage("port1的通知");
        });
      };

      port2.onmessage = function (e) {
        console.log("port2:", e.data);
        // performance.now() 页面导航到现在的时间
        // 当前时间 大于等于 当前帧结束时间,则当前帧已过期
        // 当前帧是否已过期
        let didTimeOut = performance.now() >= deadFrameTime;
        if (didTimeOut || timeRemaining() > 0) {
          if (pendingCallback) {
            pendingCallback({ didTimeOut, timeRemaining });
          }
        }
      };

      const workLoop = (idleDeadline) => {
        console.log('本帧剩余时间:', idleDeadline.timeRemaining());
        while (idleDeadline.timeRemaining() > 0 && works.length > 0) {
          // 取出待执行任务进行执行
          const work = works.shift();
          work();
        }
        if (works.length > 0) {
          console.log(`只剩余${idleDeadline.timeRemaining()},本帧时间已经到期了,等待下次调度`);
          requestIdleCallback(workLoop);
        }
      };

      // timeout:浏览器空闲时执行,但是如果已经过期了,不管还有没有空闲时间,否要执行workLoop
      requestIdleCallback(
        workLoop
        // { timeout: 1000 }
      );
    </script>
  </body>
</html>

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/621292.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vivado中ila的使用方法记录

ILA工具生成方法 一、 ILA工具介绍 在FPGA的开发中&#xff0c;当完成代码设计后&#xff0c;为了验证代码的准确性和各种不同条件下的可靠性&#xff0c;往往需要优先想到通过逻辑仿真进行相关验证。使用逻辑仿真进行验证虽然可以周密的考虑给出不同输入条件下的输出结果或交…

“智慧赋能 强链塑链”—— 汽车行业供应链管理数字化应用探讨

01车企供应链数字化的必要性 汽车供应链是一个复杂的系统&#xff0c;很多汽车企业因为供应链管理不当&#xff0c;造成资源浪费、成本高、客户满意度低等一系列问题&#xff1b;而汽车行业规模技术门槛高、配合协同复杂的特性&#xff0c;决定了其供应链缺口无法在短时间内填…

Three.js系列-报错export ‘Geometry‘ (imported as ‘THREE‘) was not found in ‘three‘

今天遇到报错export ‘Geometry’ (imported as ‘THREE’) was not found in ‘three’ port Geometry (imported as THREE) was not found in three (possible exports: ACESFilmicToneMapping, AddEquation, AddOperation, AdditiveAnimationBlendMode, AdditiveBlending, …

为什么大家都不用postman而选择 Apifox呢?

丢掉 Postman&#xff0c;Apifox 更香 作为开发者&#xff0c;丢掉 Postman 和 Jmeter吧&#xff0c;这款国产 API 工具更香&#xff0c;更安全&#xff01;一键即可导入 Postman 数据&#xff01; 一、Apifox 是什么&#xff1f; 1、Apifox 定位 Apifox Postman Swagger …

Altium Designer(AD)局域网内使用解冲突

1. Altium Designer 版本 AD15.0.8&#xff0c;电路设计软件&#xff0c;硬件工攻城狮必备技能&#xff0c;软件攻城狮也要会一点点 2. AD软件出现“Your license is already used on computer “LAPTOP-F99R6OR1” using product “AltiumDesigner” 用同事的安装包解压安装的…

Mysql 索引详细解析——底层->应用

1、索引的数据结构 1.1 概述 索引&#xff08;index&#xff09;是帮助Mysql高效获取数据的数据结构。 索引的本质&#xff1a; 索引是数据结构。简单理解为“排好序的快速查找数据结构”&#xff0c;满足特定查找算法。这些数据结构以某种方式指向数据&#xff0c; 这样就可…

期末计算机网络知识点总结

开篇提示: 因为博主图床使用的是GitHub进行存储的&#xff0c;因此当出现图片无法加载&#xff0c;可以尝试更换网络&#xff0c;或者用其他上网方法。当时想用 Gitee进行存储&#xff0c;但一直失败&#xff0c;过一段时间再试几次。目前这篇博文会一直更新&#xff0c;补充新…

Python的内置函数和保留字(关键字)

目录 内置函数 关键字&#xff08;保留字&#xff09; 内置函数 Python 解释器自带的函数叫做内置函数&#xff0c;这些函数可以直接使用&#xff0c;不需要导入某个模块。 将使用频繁的代码段封装起来&#xff0c;并给它起一个名字&#xff0c;以后使用的时候只要知道名字就可…

虹科分享 | 《面向金融行业的商业智能解决方案》白皮书

在以数据为中心的商业环境中&#xff0c;金融业面临着众多挑战&#xff0c;包括瞬息万变的市场动态、监管要求以及客户期望。金融行业从各种来源生成大量数据&#xff0c;包括交易、客户互动、市场数据和内部运营等。然而&#xff0c;如果缺乏有效的数据管理和分析&#xff0c;…

算法修炼之筑基篇——筑基二层后期(初步理解解决贪心算法)

✨博主&#xff1a;命运之光 &#x1f984;专栏&#xff1a;算法修炼之练气篇 &#x1f353;专栏&#xff1a;算法修炼之筑基篇 ✨博主的其他文章&#xff1a;点击进入博主的主页 前言&#xff1a;学习了算法修炼之练气篇想必各位蒟蒻们的基础已经非常的扎实了&#xff0c;下来…

【opencv】无法打开源文件opencv.hpp | bug记录

问题描述 今天这个bug其实比较搞笑&#xff1a; 原因分析&#xff1a; 那就是我们的VS软件没有识别到安装的库。肯定是下面三个环节哪里出错了&#xff1a; 1&#xff09;项目属性里的包含目录&#xff08;include&#xff09; 2&#xff09;项目属性里的库目录(lib) 3&…

随笔记录阿里云开发者社区Java开发高级技能自测20道题

目录 【单选】1.MyBatis中&#xff0c;主要使用哪个Java 接口来执行SQL命令&#xff1f;【单选】2.Spring中ApplicationContext的主要用法是&#xff1f;【单选】3.MySQL中&#xff0c;使用正则表达式查找news表中title以S或Q或L字母开头的所有数据&#xff0c;语句是&#xff…

【MySql】MySql的数据类型

文章目录 数据类型分类数值类型tinyint类型bit类型小数类型floatdecimal 字符串类型charvarchar日期和时间类型enum和set 数据类型分类 对于数据类型分类&#xff0c;这里简单分为数值类型&#xff08;如BIT,BOOL,INT&#xff09;&#xff0c;文本、二进制类型&#xff08;如CH…

JMeter 测试 ActiveMq

JMeter 测试 ActiveMq 的资料非常少&#xff0c; 我花了大量的时间才研究出来 关于ActiveMq 的文章请参考我另外的文章。 版本号: ActiveMq 版本号: 5.91 Jmeter 版本号: 1.13 添加ActiveMq 的jar包 将 ActiveMq 下的 "activemq-all-5.9.1.jar" 复制…

labelme安装与打包为独立exe程序(超级详细版!!!!)

文章目录 labelme安装与打包为独立exe安装打包以上全部命令直接复制粘贴就行&#xff01;&#xff01;&#xff01;&#xff01; labelme安装与打包为独立exe 按照官网给出的详细教程即可&#xff0c;不用去看一些博客&#xff08;都过时了&#xff09;。。。label官网 简要说…

Linux操作

Linux操作 一、Linux操作 1.安装yum包&#xff1a; $ yum install PACKAGE_NAME yum install mysql2.取出yum包装&#xff1a; $ yum remove PACKAGE_NAME yum remove mysql3.重新安装一个yum包&#xff1a; $ yum reinstall PACKAGE_NAME yum reinstall mysql4.搜索yum包…

tb6612电机驱动软件开发(cubeide工程调试,引脚等设置)

tb6612电机驱动软件开发(cubeide工程调试&#xff0c;引脚等设置&#xff09; 文章目录 tb6612电机驱动软件开发(cubeide工程调试&#xff0c;引脚等设置&#xff09;CLOCK(RCC)SYSGPIONVICTimer定时器配置PWM输出设置电机转速定时器编码模式普通定时器 UART串口设置 CLOCK(RCC…

unittest测试框架详解

单元测试的定义 1. 什么是单元测试&#xff1f; ​ 单元测试是指&#xff0c;对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作&#xff0c;这里的最小可测试单元通常是指函数或者类&#xff0c;一般是开发来做的&#xff0c;按照测试阶段来分&a…

Vue实现锁屏功能

这两天刚做了个新需求&#xff0c;要做个系统锁屏&#xff08;当然锁的是当前的系统&#xff09;&#xff0c;就类似于电脑锁屏似的。 共两种情况下锁屏&#xff0c;一种是无操作一定时间后自动锁屏&#xff1b;第二种是可以按下组合键&#xff08;快捷键&#xff09;主动进行锁…

利用ThreadLocal+AOP切面编程实现RPC日志

前言 最近在稍微学了一下ThreadLocal以及它的使用场景&#xff0c;同时也学了一下AOP相关的内容&#xff0c;刚好做个很常见的RPC日志来练练手。 主要思想是通过切面来拦截所有的请求&#xff0c;在请求进入切面的时候&#xff0c;可以用ThreadLocal来存储当前请求的线程专属的…