React16源码: React中的不同的expirationTime的源码实现

GEO优化内容营销策略:从规划到落地的全流程指南 GEO内容营销是通过地域化内容提升本地搜索排名、增加流量和转化率的策略。核心包括:构建本地用户画像,挖掘需求关键词;策划本地文化融合、案例研究等多样化内容;通过网站、社交媒体、本地KOL等渠道精准分发;优化本地关键词和视觉元素;监测数据并动态调整。案例显示,咖啡馆、工业企业和服装品牌通过本地化短视频、KOL合作及社群运营,显著提升了搜索排名、客流量和销售额。关键原则是内容本地化、精准分发、KOL合作、激励用户生成内容及数据驱动优化,实现高效本地市场渗透。 阅读详情

不同的 expirationTime


1 )概述

  • 在React中不仅仅有异步任务
  • 大部分情况下都是同步的任务,所以会有不同 expirationTime 的存在

2 )种类

  • A. Sync 模式,优先级最高
    • 任务创建完成之后,立马更新到真正的dom里面
    • 是一个创建即更新的流程
  • B. Async 模式, 异步模式
    • 会有一个调度
    • 包含一系列复杂的操作在里面
    • 可能会中断,所以会有一个计算出来的过期时间
    • 过期时间根据异步的两种情况,如前文所述
      • 最低优先级的异步
      • 最高优先级的异步
  • C. 指定context

3 ) 源码

  • 在 ReactFiberReconciler.js 中的 updateContainer 中
    • 调用的是 computeExpirationForFiber
      • 它接收两个参数: currentTime: ExpirationTime, fiber: Fiber
    • 这个方法来自于 ReactFiberScheduler.js 文件
      function computeExpirationForFiber(currentTime: ExpirationTime, fiber: Fiber) {
        let expirationTime;
        if (expirationContext !== NoWork) {
          // An explicit expiration context was set;
          expirationTime = expirationContext;
        } else if (isWorking) {
          if (isCommitting) {
            // Updates that occur during the commit phase should have sync priority
            // by default.
            expirationTime = Sync;
          } else {
            // Updates during the render phase should expire at the same time as
            // the work that is being rendered.
            expirationTime = nextRenderExpirationTime;
          }
        } else {
          // No explicit expiration context was set, and we're not currently
          // performing work. Calculate a new expiration time.
          if (fiber.mode & ConcurrentMode) {
            if (isBatchingInteractiveUpdates) {
              // This is an interactive update
              expirationTime = computeInteractiveExpiration(currentTime);
            } else {
              // This is an async update
              expirationTime = computeAsyncExpiration(currentTime);
            }
            // If we're in the middle of rendering a tree, do not update at the same
            // expiration time that is already rendering.
            if (nextRoot !== null && expirationTime === nextRenderExpirationTime) {
              expirationTime += 1;
            }
          } else {
            // This is a sync update
            expirationTime = Sync;
          }
        }
        if (isBatchingInteractiveUpdates) {
          // This is an interactive update. Keep track of the lowest pending
          // interactive expiration time. This allows us to synchronously flush
          // all interactive updates when needed.
          if (expirationTime > lowestPriorityPendingInteractiveExpirationTime) {
            lowestPriorityPendingInteractiveExpirationTime = expirationTime;
          }
        }
        return expirationTime;
      }
      
      • 1 )这里有一系列的判断,首先是对 expirationContext 的判断
        • 它是 ExpirationTime 类型,默认初始化值是 NoWork
        • 下面是它的一个修改场景
          function deferredUpdates<A>(fn: () => A): A {
            const currentTime = requestCurrentTime();
            const previousExpirationContext = expirationContext;
            const previousIsBatchingInteractiveUpdates = isBatchingInteractiveUpdates;
            expirationContext = computeAsyncExpiration(currentTime); // 这里
            isBatchingInteractiveUpdates = false;
            try {
              return fn();
            } finally {
              expirationContext = previousExpirationContext;
              isBatchingInteractiveUpdates = previousIsBatchingInteractiveUpdates;
            }
          }
          
          • expirationContext = computeAsyncExpiration(currentTime);
          • 可以看到 computeAsyncExpiration 这个函数对其进行修改赋值
        • 还有一种场景, 往下进行搜索
          function syncUpdates<A, B, C0, D, R>(
            fn: (A, B, C0, D) => R,
            a: A,
            b: B,
            c: C0,
            d: D,
          ): R {
            const previousExpirationContext = expirationContext;
            expirationContext = Sync; // 变成了 Sync
            try {
              return fn(a, b, c, d); // 这里是 setState 操作
            } finally {
              expirationContext = previousExpirationContext; // 最终还原
            }
          }
          
          • syncUpdates 在 ReactDOM.js 中的 flushSync API
            • flushSync: DOMRenderer.flushSync 一直溯源往上找到 ReactFiberScheduler.js 中的 flushSync
            • 这个就是 本源的 flushSync
              // TODO: Batching should be implemented at the renderer level, not within
              // the reconciler.
              function flushSync<A, R>(fn: (a: A) => R, a: A): R {
                invariant(
                  !isRendering,
                  'flushSync was called from inside a lifecycle method. It cannot be ' +
                    'called when React is already rendering.',
                );
                const previousIsBatchingUpdates = isBatchingUpdates;
                isBatchingUpdates = true;
                try {
                  return syncUpdates(fn, a); // 这里
                } finally {
                  isBatchingUpdates = previousIsBatchingUpdates;
                  performSyncWork();
                }
              }
              
            • 上述调用的是 syncUpdates,在之前的示例中,如下
              flushSync(() => {
                this.setState({
                  num: newNum,
                })
              })
              
            • 上述示例就是传入 fn 回调, 内部调用 setState
            • 在这种场景下 expirationTime 变成了 Sync
        • 以上两种情况 是给 expirationContext 进行赋值
      • 2 )当 expirationTime 变成了 Sync 就不符合第一种情况了,这时候往下走,匹配到了 isWorking
        • isWorking 表示有任务正在更新
        • 也是基于条件指定某个值
        • 这块涉及到后续任务的更新,跳过
      • 3 )没有外部强制的情况下
        • if (fiber.mode & ConcurrentMode)
        • 判断 fiber.mode 是否是 ConcurrentMode
        • 找到 ConcurrentMode 的定义处 ReactTypeOfMode.js
          export type TypeOfMode = number;
          
          export const NoContext = 0b000;
          export const ConcurrentMode = 0b001;
          export const StrictMode = 0b010;
          export const ProfileMode = 0b100;
          
        • 可见,使用二进制方式来定义的
        • 可以通过 与或 这类逻辑的操作,非常方便的组合 Mode
        • 以及判断是否有某个Mode,例如
          const a = 0b000;
          const b = 0b001;
          const c = 0b010;
          const d = 0b100;
          let mode = a; // 默认等于 a, 在后续渲染时并不知道是否有更改过
          mode & b // 如果 结果为 0 表示没有过b这种情况
          mode |= b // 这样给 mode 增加 b,这时候 mode 变成1,就对应了 b
          mode |= c // 给 mode 增加 c, 这时候 mode 变成 3,也就是 0b011
          mode & b // 这时候判断mode是否有b, 如果是1,则有b, 结果是1 对应b
          mode & c // 这时候判断mode是否有c, 如果是1,则有c, 结果是2 对应c
          
          • 这是一种巧妙的设计方式
          • 类似的,在 ReactSideEffectTags.js 中也是这么设计的
        • 回到代码里,如果是 ConcurrentMode 才会调用
        • computeInteractiveExpiration 和 computeAsyncExpiration 两个函数中的一个计算 expirationTime
          if (isBatchingInteractiveUpdates) {
            // This is an interactive update
            expirationTime = computeInteractiveExpiration(currentTime);
          } else {
            // This is an async update
            expirationTime = computeAsyncExpiration(currentTime);
          }
          
          • 关于 isBatchingInteractiveUpdates 在 interactiveUpdates 函数中被赋值为 true
            • 大部分的 React 事件产生的更新,事件中绑定回调函数,这个回调函数执行的时候
            • 大部分都是在 interactiveUpdates 情况下,也就是 isBatchingInteractiveUpdates 为 true 时
          • 后面 expirationTime += 1; 是为了区分下一个即将进行的更新和当前正在创造的更新,防止一样,强制把当前+1
        • 如果不属于,则还是 Sync
Spring AI提示词模板应用 本文介绍了使用SpringAI提示词模板的配置方法,主要步骤包括:1)在JDK17和SpringBoot3.4.4环境下引入spring-ai-alibaba1.0.0.2依赖;2)配置application.yml文件;3)创建测试控制器类处理提示词模板(.st文件);4)通过模板变量动态生成AI回复内容。演示了如何通过@RequestParam设置默认参数,实现无需前端传参即可测试AI回复功能,最终完成了一个SpringAI提示词模板的应用Demo。 阅读详情

相关推荐

OpenManus本地部署实战:从源码编译到浏览器路径优化全解析

本文详细解析了OpenManus本地部署的全过程,从源码编译到浏览器路径优化。涵盖环境准备、源码获取、模型配置、依赖安装等关键步骤,特别针对Windows系统下的chrome.exe路径修改提供了实用解决方案,帮助开发者高效完成部署并优化性能。

weixin_28826545的博客 381

React 18的新特新

React 18 新特性

小蜜蜂的博客 895

实验5 振幅调制(集成乘法器幅度调制电路)

目录5-1 振荡调制的基本工作原理一.振幅调制和调幅波1.普通调幅波(AM)(1)调幅波的表达式、波形(2)调幅波的频谱2.抑制载波双边带调幅(DSB)3.抑制载波单边带调幅(SSB)二.普通调幅波的产生电路三.抑制载波调幅的产生电路5-2 振幅调制实验电路 5-1 振荡调制的基本工作原理 根据电磁波理论知道,只有频率较高的振荡才能被天线有效地辐射。但是人的讲话声音变换为相应电信号的频率较低,不适于直接从天线上辐射。因此,为了传递信息,就必须将要传递的信息“记载”到高频振荡上去。这一“记载”过程称为调

胡毛毛的博客 3万+

十日谈 :React的更新(下)

十日谈 :React的更新欢迎阅读我的React源码学习笔记

qq_36013952的博客 888

别再魔改LWIP了!用STM32CubeMX配置F407的TCP保活(KeepAlive)与自动重连

本文详细介绍了如何通过STM32CubeMX配置STM32F407的LWIP协议栈,实现TCP保活(KeepAlive)与自动重连功能,解决网络异常断开问题。文章提供了从基础环境配置到自动重连架构设计的完整指南,帮助开发者构建高可靠的网络连接机制,适用于工业物联网和嵌入式设备开发。

weixin_27038245的博客 239

光储微电网混合储能系统的控制策略

随着社会生产力的不断提高,对不可再生资源的大量消耗,人们已经意识到发展可再生能源的重要性,因此微电网技术作为再生能源利用的有效形式被快速发展。蓄电池容量无限大是传统光储微电网混合储能系统控制策略一种理想形式,但实际上蓄电池的容量是有限度的,传统控制策略在蓄电池剩余电量达到阖值时将无法正常使用,由此提出了光储微电网混合储能系统的新型控制策略,又结合实际情况,对开关进行了改进,利用开关与二极管并联,使其拥有四种工作状态,当储能元件剩余电量达到阈值时,可自动恢复电量降低成本,提高并输出电池电能质量。

nhkg888的博客 1748

解决tldraw项目中flushSync在生命周期方法内调用的错误

在React应用开发过程中,开发者有时会遇到"flushSync was called from inside a lifecycle method"这样的警告信息。本文将以tldraw项目为例,深入分析这个问题的成因及解决方案。 ## 问题现象 当开发者在tldraw项目中使用TldrawImage组件时,浏览器控制台会出现以下警告: "flushSync was called from i...

gitblog_00042的博客 471

最全卷积总结篇(分组、深度可分离、空洞、转置等)

分组卷积(Group Convolution)是一种卷积操作方式,它最早在AlexNet中引入,并在深度学习中被广泛使用,尤其是在高效模型设计(如MobileNet和ResNeXt)中。分组卷积通过将输入特征通道分为若干组,并在每组内单独进行卷积操作,可以减少计算复杂度和参数量,同时有效利用模型的结构特性。分组卷积的工作原理通道分组:输入特征图的通道图为C_in,输出特征图的通道数为C_out,将每组的C_in和C_out分为G组,每组的通道数为C_in/G和C_out/G。组内卷积。

qq_44815135的博客 4220

记一次react 问题

react unstable_flushDiscreteUpdates

qq_42749712的博客 2747

用R语言实现“中断时间序列分析” --- R code for ITS

ITS方法可用于评估一项干预措施的效果,从水平改变和斜率改变两个角度来描述干预引起的变化。

franksui的博客 4030

基于高光谱的物质反演与分类 — 技术文章(原理详解 + 深度代码实现)

高光谱遥感 / 近场光谱采集产生逐像素上百波段的光谱曲线,是物质识别与定量反演(abundance / composition estimation)和语义分类(landcover / material class)的一把利器。本文第一部分对常用模型(线性混合模型、非线性辐射传输、稀疏反演、降维与特征选择、分类器/神经网络)进行数学推导与理论分析;第二部分给出两套完整实现:A. 基于 LMM 的约束最小二乘 / 稀疏反演流水线(含端到端评估);

VectorShift的博客 221

React 新特性 03

本系列文章主要以。

wangleijie98的博客 1227

LLaMA Factory多卡微调的实战教程(持续更新)

本文主要介绍了LLaMA Factory多卡微调的实战教程(持续更新),希望对学习大语言模型的同学们有所帮助。 文章目录 1. 前言 2. 配置环境 2.1 安装虚拟环境 2.2 安装依赖库 2.3 模型选型与下载 2.4 配置多卡环境 3. 运行代码 3.1 构建训练数据 3.2 修改配置文件 3.3 微调 3.3.1 zero3微调 3.3.2 启动API 3.3.3 模型测试

herosunly的博客 25万+

React16源码: React中更新阶段中不同类型的expirationTime之pendingTime,suspendedTime以及pingedTime的源码实现

现在发现,3种 expirationTime 的处理最终都调用了。下面是 renderRoot 中的一段代码。2.2 关于 suspendedTime。2.1 关于 pendingTime。

Wang的专栏 1014

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

React16源码: React中ReactFiberScheduler的expirationTime及nextExpirationTimeToWorkOn的源码实现

expirationTime 作用在渲染之前的,而 nextExpirationTimeToWorkOn 则是作用在渲染时的。让它在下一次执行更新之前来使用 performSyncWork 这种方式来通过同步的方式去渲染任务。这两个值在整个 render 以及 commit 的过程当中,都起着非常重要的一个作用。所以这就是这两个值它的作用, 通过指定它们来指定更新模式以及更新任务的优先级。为什么说 expirationTime 是作用在渲染前的呢?比如说, 在 renderRoot 中。

Wang的专栏 1274

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

React16源码: React中的expirationTime过期时间的计算源码实现

先看expirationTime相关的源代码,这里是异步的计算方式,它会有一个过期时间,异步任务优先级比较低,可以被打断,防止一直被打断导致不能执行,所以React给它设置了 expirationTime 过期时间,也就是在这个时间之前,都可以打断,但是如果某个时间点发现任务已经过期了,还没有被执行,则强制执行该任务

Wang的专栏 1851

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

React16源码: React中requestCurrentTime和expirationTime的源码实现补充

关于 currentTime,在计算 expirationTime 和其他的一些地方都会用到, 从它的名义上来讲,应等于performance.now() 或者 Date.now() 就是指定的当前时间, 在react整体设计当中,它是有一些特定的用处和一些特殊的设定的

Wang的专栏 1333

react源码阅读4 ExpirationTime

react更新中优先级依赖的标识ExpirationTime。阅读React包的源码版本为16.8.6。   这一章节,让我们抛弃掉react代码中的联系,单纯的来看ExpirationTime以及一些计算方式。 ExpirationTime是什么。   ExpirationTime是一个数字,你可以在react-reconciler包下的ReactFiberExpirationTime.js文件中找到它的定义。 export type ExpirationTime = number; Expiratio

tangding12的博客 524

React16源码: React中的updateMemoComponent的源码实现

我们通过React.memo这个方法创建的组件,它的所有props是直接作用于传入的 function component的。,它会把props作为我自己当前这个组件。为什么在这里它不使用。

Wang的专栏 1012

React16源码: React中的updateMode的源码实现

`Mode` 组件是 react提供给我们的原生组件, 一共有两个: `ConcurrentMode` 和 `StrictMode`, 对于这两个 Mode 的更新过程最终调用的都是 `updateMode` 的方法, 它们执行的过程非常的简单,就是通过 `reconcileChildren` 去创建children就可以了

Wang的专栏 1056

React16源码: React中调度之requestWork的源码实现

在 scheduleWork 中,找到了创建更新的fiber对应的root节点, 然后对它进行了一些操作之后,调用了 `requestWork`,开始请求工作, 在 requestWork 里面它会做哪些东西呢?首先我们要把这个root节点加入到调度队列当中, 然后判断是否是批量更新, 最后再根据 expirationTime 的类型来判断调度的类型

Wang的专栏 1144

React16源码: React中的renderRoot的源码实现

renderRoot 是一个非常复杂的方法, 它调用 workLoop 进行循环单元更新, 并且捕获错误并进行处理,最后,在走完流程之后要进行善后

Wang的专栏 1397

React16源码: React中的schedule调度整体流程

React Fiber Scheduler 是 react16 最核心的一部分,这块在这个包中这个包的核心是 fiber reconciler,也即是 fiber 结构fiber的结构帮助我们把react整个树的应用,更新的流程,能够拆成每一个fibrer对象为单元的一个更新的流程这种单元的形式把更新拆分出来之后,给每个不同的任务提供一个优先级,以及我们在更新的过程当中,可以中断因为我们记录更新到了哪一个单元,中断了之后,可以过一会儿再回过头来,继续从这个单元开始,继续之前没有做完的更新。

Wang的专栏 1604

React16源码: React中的update和updateQueue的源码实现

在 `ReactDOM.render` 过程中,还需要创建一个 update 对象, `update` 用于记录组件状态的改变的一个对象,它存放于Fiber对象的 `updateQueue` 中,`updateQueue`,它是一个单向链表的结构,一次整体的更新过程当中, 可能在这个queue里会存在多 Update

Wang的专栏 1665

React16源码: React中调度之scheduleWork的源码实现

定位到 packages/react-reconciler/src/ReactFiberScheduler.js。拿之前的一个 Fiber Tree 节点来举例。当中,它需要去找到更新对应的。如果符合条件需要重置 stack。如果符合条件就去请求工作调度。这几个方法最终都调用了。

Wang的专栏 1525

React16源码: React中的resetChildExpirationTime的源码实现

在 `completeUnitOfWork` 当中,有一步比较重要的一个操作,就是重置`childExpirationTime`, childExpirationTime 是非常重要的一个时间节点,它用来记录某一个节点的子树当中,目前优先级最高的那个更新, 整个应用的调度过程当中使用的都是root节点,在 scheduleWork 的时候,即便我们创建更新的那个节点,是我们写的某一个组件

Wang的专栏 969
上一篇: React16源码: React中的expirationTime过期时间的计算源码实现
下一篇: React16源码: React中的setState和forceUpdate源码实现
Wang's Blog
博客等级 码龄12年 7434粉丝 2421原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值