当前位置: 首页 > news >正文

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

requestCurrentTime


1 )概述

  • 关于 currentTime,在计算 expirationTime 和其他的一些地方都会用到
    • 从它的名义上来讲,应等于performance.now() 或者 Date.now() 就是指定的当前时间
    • 在react整体设计当中,它是有一些特定的用处和一些特殊的设定的
    • 比如说在一次渲染中产生的更新,需要使用相同的时间
    • 在一次批处理的更新中,应该得到相同的时间
    • 还有就是挂起的任务用于记录的时候,应该也是相同的

2 )源码

function requestCurrentTime() {// requestCurrentTime is called by the scheduler to compute an expiration// time.//// Expiration times are computed by adding to the current time (the start// time). However, if two updates are scheduled within the same event, we// should treat their start times as simultaneous, even if the actual clock// time has advanced between the first and second call.// In other words, because expiration times determine how updates are batched,// we want all updates of like priority that occur within the same event to// receive the same expiration time. Otherwise we get tearing.//// We keep track of two separate times: the current "renderer" time and the// current "scheduler" time. The renderer time can be updated whenever; it// only exists to minimize the calls performance.now.//// But the scheduler time can only be updated if there's no pending work, or// if we know for certain that we're not in the middle of an event.if (isRendering) {// We're already rendering. Return the most recently read time.return currentSchedulerTime;}// Check if there's pending work.findHighestPriorityRoot();if (nextFlushedExpirationTime === NoWork ||nextFlushedExpirationTime === Never) {// If there's no pending work, or if the pending work is offscreen, we can// read the current time without risk of tearing.recomputeCurrentRendererTime();currentSchedulerTime = currentRendererTime;return currentSchedulerTime;}// There's already pending work. We might be in the middle of a browser// event. If we were to read the current time, it could cause multiple updates// within the same event to receive different expiration times, leading to// tearing. Return the last read time. During the next idle callback, the// time will be updated.return currentSchedulerTime;
}
  • 第一种情况,在 isRendering 的时候,会直接返回 currentSchedulerTime, 这个 schedulerTime
    • isRendering 只有在 performWorkOnRoot 的时候才被设置为 true
    • 而 performWorkOnRoot 是在 performWork 中被循环调用的
    • performWorkOnRoot 的前后,都会重设 currentSchedulerTime
    • 这样,在 performWorkOnRoot 的时候, isRendering 被设定为 true,并且是一个同步的方法
    • 使用 performWorkOnRoot 的时候, 后期会调用 render 和 commit 两个阶段
    • 在上述两个阶段里,都有可能调用组件的生命周期方法,在这里有可能产生更新
    • react的设定是,在当前渲染流程中,如果在生命周期方法里触发了新的更新
    • 那么它计算 expirationTime 的时间,需要一个固定的时间,所以统一返回 currentSchedulerTime
    • 这个 currentSchedulerTime 就是在调用 performWorkOnRoot 之前算出来的时间
    • requestCurrentTime 的 if (isRendering) return currentScheudlerTime的设定
  • 第二种情况
    • 调用 findHighestPriorityRoot 找到调度队列中,优先级最高的任务
    • 如果符合 if (nextFlushedExpirationTime === NoWork || nextFlushedExpirationTime === Never)
      • 目前没有任务进行或正在更新的组件是从未展现的组件
      • 这时候,重新计算 renderTime recomputeCurrentRendererTime();
      • 并且赋值 currentSchedulerTime = currentRendererTime;
      • 最终 return currentSchedulerTime
    • 这里和 batchedUpdates 里面类似
      • 创建了 事件的回调,多次调用 setState 会创建多个更新
      • 计算多次 expirationTime
      • 如果没有做这类处理 requestCurrentTime 都去计算一个时间
      • 就会导致返回的时间不一致,因为时间不一致,导致计算出来的 expirationTime不一致
      • 那么就导致任务优先级不一致,它们会分批次的进行更新,就会导致问题
      • 在异步的模式下,即便只有在最后一次,回调调用完之后才会去调用 performWork
      • 但是因为任务优先级不同,会导致分多次进行调用
    • 所以,通过上述判断来规避此类问题
    • 第一次调用 setState 之后,就在一个root上创建一个更新
    • 从 firstScheduledRoot 到 lastScheduledRoot 里面至少会有一个
    • 即将要执行的更新,在有一个的情况下,上述 if 就不满足了,就不会直接计算时间
    • 直接返回 currentSchedulerTime 这个已保存的时间

expirationTime


1 ) 概述

  • 在计算 expirationTime 之前,我们计算的时间是预先处理过的
  • 在 requestCurrentTime 函数中有一个 recomputeCurrentRendererTime

2 )源码

// /packages/react-reconciler/src/ReactFiberScheduler.js
function recomputeCurrentRendererTime() {const currentTimeMs = now() - originalStartTimeMs;currentRendererTime = msToExpirationTime(currentTimeMs);
}// packages/react-reconciler/src/ReactFiberExpirationTime.js
// 1 unit of expiration time represents 10ms.
export function msToExpirationTime(ms: number): ExpirationTime {// Always add an offset so that we don't clash with the magic number for NoWork.// ms / UNIT_SIZE 为了防止 10ms 之内的误差,两个时间差距在10ms以内,两个时间看做一致,最终计算出来的优先级也是一致return ((ms / UNIT_SIZE) | 0) + MAGIC_NUMBER_OFFSET; // UNIT_SIZE 是 10, const MAGIC_NUMBER_OFFSET 是 2
}
function computeExpirationBucket(currentTime,expirationInMs,bucketSizeMs,
): ExpirationTime {return (MAGIC_NUMBER_OFFSET +ceiling(currentTime - MAGIC_NUMBER_OFFSET + expirationInMs / UNIT_SIZE,bucketSizeMs / UNIT_SIZE,));
}
export function expirationTimeToMs(expirationTime: ExpirationTime): number {return (expirationTime - MAGIC_NUMBER_OFFSET) * UNIT_SIZE;
}
  • 在后续 computeExpirationBucket 中 currentTime - MAGIC_NUMBER_OFFSET
  • 所以 MAGIC_NUMBER_OFFSET 没有影响到 真正时间的计算
  • 误差在10ms以内的,前后两个用于计算 expirationTime 的 currentTime
  • 它们的误差会被抹平,就是 msToExpirationTime 这个方法被设计的意义
  • 最终使用具体的时间设置timeout, 判断是否过期的时候,会通过 expirationTimeToMs 把这个时间转回来

相关文章:

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

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

【论文阅读】Deep Graph Contrastive Representation Learning

目录 0、基本信息1、研究动机2、创新点3、方法论3.1、整体框架及算法流程3.2、Corruption函数的具体实现3.2.1、删除边(RE)3.2.2、特征掩盖(MF) 3.3、[编码器](https://blog.csdn.net/qq_44426403/article/details/135443921)的设…...

设计模式-简单工厂

设计模式-简单工厂 简单工厂模式是一个集中管理对象创建,并根据条件生成所需类型对象的设计模式,有助于提高代码的复用性和维护性,但可能会导致工厂类过于复杂且违反开闭原则。 抽象提取理论: 封装对象创建过程解耦客户端与产品…...

Django ORM 中的单表查询 API(1)

在 Django 中,对象关系映射(ORM)提供了一种功能强大、表现力丰富的数据库交互方式。ORM 允许开发人员使用高级 Python 代码执行数据库查询,从而更轻松地处理数据库实体。 下面,我们将探讨 Django ORM 中单表查询 API …...

电子雨html代码

废话不多说下面是代码&#xff1a; <!DOCTYPE html><html lang"en"><head><meta charset"UTF-8"><title>Code</title><style>body{margin: 0;overflow: hidden;}</style></head><body><c…...

xadmin基于Django的后台管理系统安装与使用

xadmin是基于Django的后台管理系统 官网&#xff1a;http://sshwsfc.github.io/xadmin/ github地址&#xff1a;https://github.com/sshwsfc/xadmin 安装方式 pip安装 pip install xadmin在setting配置中添加&#xff1a; INSTALLED_APPS [xadmin,crispy_forms, ]在urls.py…...

[go语言]输入输出

目录 知识结构 输入 1.Scan ​编辑 2.Scanf 3.Scanln 4.os.Stdin --标准输入&#xff0c;从键盘输入 输出 1.Print 2.Printf 3.Println 知识结构 输入 为了展示集中输入的区别&#xff0c;将直接进行代码演示。 三者区别的结论&#xff1a;Scanf格式化输入&#x…...

【SpringBoot系列】AOP详解

🤵‍♂️ 个人主页:@香菜的个人主页,加 ischongxin ,备注csdn ✍🏻作者简介:csdn 认证博客专家,游戏开发领域优质创作者,华为云享专家,2021年度华为云年度十佳博主 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞👍🏻 收…...

openssl3.2 - 官方demo学习 - signature - rsa_pss_hash.c

文章目录 openssl3.2 - 官方demo学习 - signature - rsa_pss_hash.c概述笔记END openssl3.2 - 官方demo学习 - signature - rsa_pss_hash.c 概述 对私钥对明文做签名(摘要算法为SHA256) 用公钥对密文做验签(摘要算法为SHA256) 笔记 /*! \file rsa_pss_hash.c \note openss…...

Redis相关知识点

1.什么是Redis Redis (REmote DIctionary Server) 是用 C 语言开发的一个开源的高性能键值对&#xff08;key-value&#xff09;数据库&#xff0c;它支持网络&#xff0c;可基于内存亦可持久化&#xff0c;并提供多种语言的API。Redis具有高效性、原子性、支持多种数据结构、…...

嵌入式开发--STM32G4系列片上FLASH的读写

这个玩意吧&#xff0c;说起来很简单&#xff0c;就是几行代码的事&#xff0c;但楞是折腾了我大半天时间才搞定。原因后面说&#xff0c;先看代码吧&#xff1a; 读操作 读操作很简单&#xff0c;以32位方式读取的时候是这样的&#xff1a; data *(__IO uint32_t *)(0x080…...

嵌入式-Stm32-江科大基于标准库的GPIO的八种模式

文章目录 一&#xff1a;GPIO输入输出原理二&#xff1a;GPIO基本结构三&#xff1a;GPIO位结构四&#xff1a;GPIO的八种模式道友&#xff1a;相信别人&#xff0c;更要一百倍地相信自己。 &#xff08;推荐先看文章&#xff1a;《 嵌入式-32单片机-GPIO推挽输出和开漏输出》…...

2024年1月17日Arxiv热门NLP大模型论文:THE FAISS LIBRARY

Meta革新搜索技术&#xff01;提出Faiss库引领向量数据库性能飞跃 引言&#xff1a;向量数据库的兴起与发展 随着人工智能应用的迅速增长&#xff0c;需要存储和索引的嵌入向量&#xff08;embeddings&#xff09;数量也在急剧增加。嵌入向量是由神经网络生成的向量表示&…...

深度解析JVM类加载器与双亲委派模型

概述 Java虚拟机&#xff08;JVM&#xff09;是Java程序运行的核心&#xff0c;其中类加载器和双亲委派模型是JVM的重要组成部分。本文将深入讨论这两个概念&#xff0c;并解释它们在实际开发中的应用。 1. 什么是类加载器&#xff1f; 类加载器是JVM的一部分&#xff0c;负…...

前端下载文件流,设置返回值类型responseType:‘blob‘无效的问题

前言&#xff1a; 本是一个非常简单的请求&#xff0c;即是下载文件。通常的做法如下&#xff1a; 1.前端通过Vue Axios向后端请求&#xff0c;同时在请求中设置响应体为Blob格式。 2.后端相应前端的请求&#xff0c;同时返回Blob格式的文件给到前端&#xff08;如果没有步骤…...

C++核心编程——类和对象(一)

本专栏记录C学习过程包括C基础以及数据结构和算法&#xff0c;其中第一部分计划时间一个月&#xff0c;主要跟着黑马视频教程&#xff0c;学习路线如下&#xff0c;不定时更新&#xff0c;欢迎关注。 当前章节处于&#xff1a; ---------第1阶段-C基础入门 ---------第2阶段实战…...

脱模斜度是什么意思,为什么要有脱模斜度,没有斜度不行吗?

问题描述&#xff1a;脱模斜度是什么意思&#xff0c;为什么要有脱模斜度&#xff0c;没有斜度不行吗&#xff1f; 问题解答&#xff1a; 脱模斜度是指在模具中的零件在脱模&#xff08;从模具中取出&#xff09;过程中相对于模具开合方向的倾斜程度。在模具设计和制造中&…...

【现代密码学】笔记9-10.3-- 公钥(非对称加密)、混合加密理论《introduction to modern cryphtography》

【现代密码学】笔记9-10.3-- 公钥&#xff08;非对称加密&#xff09;、混合加密理论《introduction to modern cryphtography》 写在最前面8.1 公钥加密理论随机预言机模型&#xff08;Random Oracle Model&#xff0c;ROM&#xff09; 写在最前面 主要在 哈工大密码学课程 张…...

牛客-寻找第K大、LeetCode215. 数组中的第K个最大元素【中等】

文章目录 前言牛客-寻找第K大、LeetCode215. 数组中的第K个最大元素【中等】题目及类型思路思路1&#xff1a;大顶堆思路2&#xff1a;快排二分随机基准点 前言 博主所有博客文件目录索引&#xff1a;博客目录索引(持续更新) 牛客-寻找第K大、LeetCode215. 数组中的第K个最大元…...

MySQL的各种日志

目录 一、错误日志 二、二进制日志 1、介绍 2、作用 3、相关信息 4、日志格式 5、查看二进制文件 6、二进制日志文件删除 三、查询日志 四、慢日志 一、错误日志 记录MySQL在启动和停止时&#xff0c;以及服务器运行过程中发生的严重错误的相关信息&#xff0c;当数据库…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

【实施指南】Android客户端HTTPS双向认证实施指南

&#x1f510; 一、所需准备材料 证书文件&#xff08;6类核心文件&#xff09; 类型 格式 作用 Android端要求 CA根证书 .crt/.pem 验证服务器/客户端证书合法性 需预置到Android信任库 服务器证书 .crt 服务器身份证明 客户端需持有以验证服务器 客户端证书 .crt 客户端身份…...