React18原理: 再聊Fiber架构下的时间分片

时间分片

  • react的任务可以被打断,其实就是基于时间分片的
  • 人眼最高能识别的帧数不超过30帧,电影的帧数差不多是在24
  • 浏览器的帧率一般来说是60帧,也就是每秒60个画面, 平均一个画面大概是16.5毫秒左右
  • 浏览器正常的工作流程是运算渲染,运算,渲染运算渲染
  • 在浏览器里面一个运算,加上一个渲染就是一帧
  • 总的来讲,可以理解为下面这张图
  • 比如 frame 是一帧,一个 Frame 就是16毫秒左右
  • 黑色部分是浏览器的渲染,蓝色部分是js的运算
  • 在16毫秒以内(一帧), 浏览器会重新渲染画面,然后再加上JS的一轮事件循环的执行
  • 根据任务队列循环下去,一秒 60 帧,每一帧都是 js的执行 + 浏览器的渲染
  • 但是, js它是单线程的, 会阻塞浏览器渲染, 假如 js执行时间超长,占了 3 ~ 4帧
  • js执行的时候,浏览器是不能渲染的,那这个时候会有页面卡顿的感觉
    • 实际上这个时候是 js 在执行
    • 这个也是react它去递归渲染的时候的问题
    • 递归渲染,它就是属于长进程,相当于在 render 的时候 js 一直把渲染进程给卡住
  • 这个是哥很苦恼的问题,所以诞生了fiber架构, react希望能够把任务分片处理
  • 这个时候就提到了一个概念,就是 fiber reconciler 要做的事情
  • 它如何让我们把时间分片,然后让又让浏览器不卡顿的呢?
    • 其实特别的巧妙,谷歌浏览器底层提供的一个东西叫做 requestIdleCallback
    • 前面说到一帧(16ms左右) 是 渲染 + js的执行
    • 有时候浏览器比较空闲,有可能一帧不需要 16ms,可能需要6ms, 那剩下的10ms可以执行长任务
    • 当剩下的10ms用完,可以把浏览器的渲染权利再还给浏览器
    • 这个时候进入下一帧的浏览器的画面,继续渲染,渲染完之后又有剩余时间
    • 接着再执行这个长进程,简单来说,就是把长进程拆分成一个个很小的任务
    • 它利用浏览器每一帧的空闲时间去执行,这样就实现了任务的打断,而且还不阻塞浏览器的渲染
  • 也就是说,本来一个任务要执行1秒,但是实际上react的fiber架构可能让这个1秒执行的时间更长
  • 因为任务的拆分其实是增加了这个计算的开销的,但是,它却是在我们每一帧的空闲时间去执行的
  • 虽然执行的整体时间可能变长,但是让用户的感觉没有那么卡顿,所以它的体验是提升了的
  • 参考之前 React 16的时间片:https://blog.csdn.net/Tyro_java/article/details/135586572

关于 requestIdleCallback

  • 文档:https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestIdleCallback

  • window.requestIdleCallback() 方法插入一个函数,这个函数将在浏览器空闲时期被调用

  • 这使开发者能够在主事件循环上执行后台和低优先级工作,而不会影响延迟关键事件,如动画和输入响应

  • 函数一般会按先进先调用的顺序执行,然而,如果回调函数指定了执行超时时间timeout,则有可能为了在超时前执行函数而打乱执行顺序

  • requestIdleCallback(callback)

  • requestIdleCallback(callback, options)

    • callback
      • 一个在事件循环空闲时即将被调用的函数的引用。函数会接收到一个名为 IdleDeadline 的参数
      • 这个参数可以获取当前空闲时间以及回调是否在超时时间前已经执行的状态
    • options 可选
      • 包括可选的配置参数。具有如下属性
        • timeout
          • 如果指定了 timeout,并且有一个正值,而回调在 timeout 毫秒过后还没有被调用
          • 那么回调任务将放入事件循环中排队,即使这样做有可能对性能产生负面影响
  • 返回值是一个ID,可以把它传入 Window.cancelIdleCallback() 方法来结束回调

requestIdleCallback 和 requestAnimationFrame 的区别


1 )react fiber 引起的关注

  • 组件树转换为链表,可分段渲染
  • 渲染时可以暂停,去执行其他高优先任务,空闲时再继续渲染
  • 如何判断空闲?requestIdleCallback

2 ) 区别

  • requestAnimationFrame 每次渲染完都会执行,高优

  • requestIdleCallback 空闲时才会执行,低优

    let curWidth = 100
    const maxWidth = 400
    
    function addWidth() {
      curWidth = curWidth + 3
      box.style.width = `${curWidth} px`
      if (curWidth < maxWidth) {
        widndow.requestAnimationFrame(addWidth) // 时间不用自己控制 高优先级
        widndow.requestIdleCallback(addWidth) // 时间不用自己控制 繁忙时不会执行
      }
    }
    
    addWidth()
    
  • 对比

    console.info('start')
    window.requestIdleCallback(()=>{
      console.log('requestIdleCallback')
    })
    window.requestAnimationFrame(()=>{
      console.log('requestAnimationFrame')
    })
    setTimeout(()=>{
      console.log('setTimeout')
    })
    console.info('end')
    
  • 执行顺序

    • start
    • end
    • timeout 优先级更高
    • requestAnimationFrame 宏任务优先级较高
    • requestIdleCallback 宏任务优先级较低
  • 总结

    • 两者都是宏任务
    • 需要等待dom渲染完才会执行

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(已解决)将overleaf上的文章paper上传到arxiv上遇到的问题。

文章目录 前言初级问题后续问题 前言 首先说一点&#xff0c;将paper的pdf文件直接上传arxiv是不行的&#xff0c;arxiv要求我们要上传源文件&#xff0c;所以才这么麻烦。 初级问题 首先上传文件之后有可能会在下面这个界面出现问题&#xff0c;这里一般都比较常见的问题&a…

【二叉树】层序遍历

目录 层序遍历概念&结构 层序遍历的实现 整体思路 代码实现 图示理解 BT升级 整体思路 代码实现 图示理解​ 应用 题目 前序&中序&后序遍历&#xff1a;深度优先遍历dfs 层序遍历&#xff1a;广度优先遍历bfs 层序遍历概念&结构 层序遍历&#xf…

C++ | string类按位赋值小技巧

一切的起因是string类的谜之初始化。 在写代码的时候&#xff0c;我发现即使没有用字符串初始化string对象&#xff0c;也可以对string对象进行下标操作&#xff0c;就像这样&#xff1a; #include<iostream> #include<string> using namespace std; int main() {…

春晚魔术和约瑟夫问题

春晚的魔术实际上是一个约瑟夫问题&#xff0c;最终的结果是魔术开始时确定的几个变量确定好的&#xff0c;扑克牌只是道具和障眼法。网上一查这个问题发现颇有历史渊源&#xff0c;17世纪的法国数学家加斯帕在《数目的游戏问题》中讲了这样一个故事&#xff1a;15个教徒和15 个…

JavaScript 遍历文档生成目录结构

JavaScript 遍历文档生成目录结构 要遍历 HTML 文档并生成目录结构&#xff0c;你可以使用 JavaScript 来进行 DOM 操作和遍历。以下是一个简单的示例代码&#xff0c;演示了如何遍历文档中的标题元素&#xff08;例如 <h1>、<h2>、<h3> 等&#xff09;&…

2024.02.11作业

1.请使用递归实现n! #include <stdio.h> #include <stdlib.h> #include <string.h>int func(int n) {if (n 1){return 1;}return func(n - 1) * n; }int main() {int n 5;printf("%d\n", func(5));return 0; } 2.请使用递归实现0-n的和 #inclu…

《21天精通IPv4 to IPv6》第0天:IPv4至IPv6的必要性与互联网IP资源发展趋势浅谈

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

Java常用类与基础API--String的实例化与连接操作

文章目录 一、String实例化的两种方式&#xff08;1&#xff09;两种方式&#xff08;2&#xff09;举例1、案例12、案例2 &#xff08;3&#xff09;内存分配&#xff08;4&#xff09;面试题1、题12、题2 二、String的连接操作&#xff08;1&#xff09;案例1、案例剖析2、in…

C++: const 的 权限放大缩小!

目录 概念 引用与const 关于上述的第一段代码&#xff1a; 关于上诉的第二段代码&#xff1a; const 使用指针进行权限的放大和缩小&#xff1a; 注意事项&#xff1a; const 与 成员函数 const 修饰 成员函数的规则&#xff1a; 概念 关于权限的放大和缩小问题&am…

【C++】【类和对象】拷贝构造函数

1.拷贝构造函数的特性&#xff1a; 1.拷贝构造函数用来构造一个与已存在对象一摸一样的对象 它只有单个形参&#xff0c;该形参是对本类类型对象的引用(一般常用const修饰)&#xff0c;在用已存在的类类型对象创建新对象时由编译器自动调用。 2.拷贝构造函数是构造函数的一种重…

gcore服务器设置root账号密码登录

这个厂商很奇怪&#xff0c;默认只能用centos用户与公钥登录&#xff0c;但是这样有时候很麻烦。 他默认开启了SELinux&#xff0c;和强制ssh密钥登录。 下面所有操作在root模式下进行 SELinux设置为兼容模式 setenforce 0vi /etc/selinux/config然后将文件中的SELINUXenfo…

分享88个表单按钮JS特效,总有一款适合您

分享88个表单按钮JS特效&#xff0c;总有一款适合您 88个表单按钮JS特效下载链接&#xff1a;https://pan.baidu.com/s/1v-qcl8bv2kxZ8a98Xo9UAg?pwd8888 提取码&#xff1a;8888 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;…

滑动小短剧影视微信小程序源码/带支付收益等模式

仿抖音滑动小短剧影视微信小程序源码&#xff0c;带支付收益等模式、支持无限滑动&#xff1b;高性能滑动、预加载、视频预览&#xff0c;支持剧情介绍&#xff0c;集合壁纸另外仿抖音滑动效果&#xff1b;支持会员模式&#xff0c;支持用户单独购买等等多功能。 丰富的后台设…

备战蓝桥杯---数学基础3

本专题主要围绕同余来讲&#xff1a; 下面介绍一下基本概念与定理&#xff1a; 下面给出解这方程的一个例子&#xff1a; 下面是用代码实现扩展欧几里得算法&#xff1a; #include<bits/stdc.h> using namespace std; int gcd(int a,int b,int &x,int &y){if(b…

极狐GitLab 使用阿里云作为 OmniAuth 身份验证 provider

使用阿里云作为 OmniAuth 身份验证 provider 您可以启用阿里云 OAuth 2.0 OmniAuth provider并使用您的阿里云账户登录极狐GitLab。 创建阿里云应用 登录阿里云平台&#xff0c;在上面创建一个应用。阿里云会生成一个 client ID and secret key 供您使用。 登录到阿里云平台…

STM32Cubmax AD采集

一、基本概念 二、项目 AD函数结构体 typedef struct { uint32_t Mode; // ADC 工作模式选择 FunctionalState ScanConvMode; /* ADC 扫描&#xff08;多通道&#xff09; 或者单次&#xff08;单通道&#xff09;模式选择 */ FunctionalState ContinuousConvMode; // ADC 单…

【JavaEE】_HTML常用标签

目录 1.HTML结构 2. HTML常用标签 2.1 注释标签 2.2 标题标签&#xff1a;h1~h6 2.3 段落标签&#xff1a;p 2.4 换行标签&#xff1a;br 2.5 格式化标签 2.6 图片标签&#xff1a;img 2.7 超链接标签&#xff1a;a 2.8 表格标签 2.9 列表标签 2.10 表单标签 2.10…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 2月11日,星期日

每天一分钟&#xff0c;知晓天下事&#xff01; 2024年2月11日 星期日 农历正月初二 1、 2024年总台春晚传播数据创下新纪录&#xff1a;全媒体累计触达267亿次&#xff0c;较去年增长29%。 2、 交通运输部&#xff1a;除夕全社会跨区域人员流动量超1.9亿人次。 3、 微信&am…

Backtrader 文档学习- Sizers

Backtrader 文档学习- Sizers 1.概述 智能仓位 Strategy提供了交易方法&#xff0c;即&#xff1a;buy&#xff0c;sell和close。看一下buy的定义&#xff1a; def buy(self, dataNone,sizeNone, priceNone, plimitNone,exectypeNone, validNone, tradeid0, **kwargs):注意&…

电子电器架构 —— 区域控制器是未来架构的正解吗?

电子电器架构 —— 区域控制器是未来架构的正解吗? 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师(Wechat:gongkenan2013)。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 本就是小人物,输了就是输了,不要在意别人怎么看自己。江湖一碗茶…