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

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

requestWork


1 )概述

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

2 )源码

react-reconciler/src/ReactFiberScheduler.js
找到 requestWork

// requestWork is called by the scheduler whenever a root receives an update.
// It's up to the renderer to call renderRoot at some point in the future.
function requestWork(root: FiberRoot, expirationTime: ExpirationTime) {addRootToSchedule(root, expirationTime);if (isRendering) {// Prevent reentrancy. Remaining work will be scheduled at the end of// the currently rendering batch.return;}if (isBatchingUpdates) {// Flush work at the end of the batch.if (isUnbatchingUpdates) {// ...unless we're inside unbatchedUpdates, in which case we should// flush it now.nextFlushedRoot = root;nextFlushedExpirationTime = Sync;performWorkOnRoot(root, Sync, true);}return;}// TODO: Get rid of Sync and use current time?if (expirationTime === Sync) {performSyncWork();} else {scheduleCallbackWithExpirationTime(root, expirationTime);}
}
  • 这里,它接受的参数 一个是 root,另外一个是 expirationTime
    • 这个 expirationTime 并不是我们在创建更新的时候的 expirationTime
    • 它是经过一系列处理之后得到的 expirationTime,它是用来记录任务的过期时间的
  • 进来之后的第一个方法是 addRootToSchedule
    function addRootToSchedule(root: FiberRoot, expirationTime: ExpirationTime) {// Add the root to the schedule.// Check if this root is already part of the schedule.if (root.nextScheduledRoot === null) {// This root is not already scheduled. Add it.root.expirationTime = expirationTime;if (lastScheduledRoot === null) {firstScheduledRoot = lastScheduledRoot = root;root.nextScheduledRoot = root;} else {lastScheduledRoot.nextScheduledRoot = root;lastScheduledRoot = root;lastScheduledRoot.nextScheduledRoot = firstScheduledRoot;}} else {// This root is already scheduled, but its priority may have increased.const remainingExpirationTime = root.expirationTime;if (remainingExpirationTime === NoWork ||expirationTime < remainingExpirationTime) {// Update the priority.root.expirationTime = expirationTime;}}
    }
    
    • 判断 if (root.nextScheduledRoot === null) , 符合则进行更新
      • 说明这个 root 之前没有进入过调度
      • 内部如果 lastScheduledRoot 为空
        • 注意 firstScheduledRoot 和 lastScheduledRoot 是单项链表结构
        • 用于存储react中的所有 root 的调度关系
        • 如果存在多个root, 可能会形成一个链表的结构
        • 对于只有一个root的情况,只会存在 root.nextScheduledRoot = root 即,等于自己这种情况
        • 这种情况会出现,是因为,先有了一个异步调度的任务
        • 因为一次一个时间片内执行不完,执行不完,把JS的执行权交给浏览器
        • 浏览器这个时候触发了 react 当中的一个新的更新
        • 然后这个更新进来的时候,在react里面,它总共有两种不同优先级的更新
        • 这个时候就会调用两次 addRootToSchedule
        • 这个时候 root.nextScheduledRoot = root 就等于它自己
        • 当然也会存在着有多个root的情况,这个时候就会形成一个链条
        • 这边就是通过判断是否存在 lastScheduledRoot 来判断现在是否有任务正在进行调度
        • 如果没有的话,我们就把first和last直接赋值成root就可以了
        • 那如果有的话,更新 lastScheduleddRoot及其nextSchedulRoot
        • 这就是一个把当前的这个root插到这个调度队列的最后一个的操作
        • 即单项链表插入到最后一个的操作
    • 如果已经进入过调度
      • 获取当前的 expirationTime 并进行判断
      • 如果当前的 expirationTime 是 NoWork 或 新的调度的 expirationTime 比当前任务优先级大
      • 则更新 root.expirationTime 成最高优先级
      • 因为 expirationTime 必须是 root 上优先级最高的
      • 我们要先执行优先级高的任务
      • 对于 root 来说,如果是一个异步调度,expirationTime 最小的任务,过期时间最少
      • 进入到后期调度的过程中,按照比它优先级低的来做,等到它的过期时间到了
      • 我们的调度进程中的判断标准还没有认为过期,就不会强制执行,从而导致任务被推迟
      • 所以,必须把 root.expirationTime 设置成优先级最高的
  • 接下来,判断是否在渲染中,if (isRendering)
    • 说明调度在执行了,这里直接 return
    • react 的调度是有个循环的,会循环 firstScheduledRoot 和 lastScheduledRoot 上面的任务
    • 最终把所有任务更新完,之后把 firstScheduledRoot 和 lastScheduledRoot 清空成 null
    • isRendering 说明循环已经开始,直接return就行
  • 接下来进入批处理的判断, if (isBatchingUpdates)
    • isBatchingUpdates 和 isUnbatchingUpdates 是两个全局变量
    • 是批处理相关的,先跳过
  • 最后,通过 expirationTime是否为 Sync的判断
    • 如果是 Sync,则调用 performSyncWork 方法
      • 相当于同步调用 js 代码,一直执行到结束为止
      • 无法被打断,如果层级很深,则会占用js较长时间,可能导致应用卡顿
      • 在以前版本没有 async 的情况,都是执行 performSyncWork
      • 这样,它的瓶颈是很大的,性能不好
      • 在 react16之后,保留了 sync 的模式,因为应用可能需要这种场景
    • 如果不是,则调用 scheduleCallbackWithExpirationTime 方法
      • 这里进行异步的调度
      • 这里进入了 react 中的独立的包 scheduler
      • 这个包帮我们使用类似 requestIdleCallback 的方式帮助我们在浏览器有空闲的情况下
      • 去执行不是很重要的任务,并且给我们设置 deadline
      • 在 deadline 之前可以执行,在这个 deadline 之后,必须先把执行权交还给浏览器
      • 再等它有空,再来执行任务
      • 这个包用于提升前端应用开发的效率

相关文章:

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

requestWork 1 &#xff09;概述 在 scheduleWork 中&#xff0c;找到了创建更新的fiber对应的root节点然后对它进行了一些操作之后&#xff0c;调用了 requestWork&#xff0c;开始请求工作在 requestWork 里面它会做哪些东西呢&#xff1f; 首先我们要把这个root节点加入到调…...

【白话机器学习的数学】读书笔记(3)学习分类(感知机、逻辑回归)

三、学习分类 1.分类的目的 找到一条线把白点和黑点分开。这条直线是使权重向量成为法线向量的直线。(解释见下图) 直线的表达式为&#xff1a; ω ⋅ x ∑ i 1 n ω i ⋅ x i 0 \omegax \sum_{i1}^n\omega_i x_i 0 ω⋅xi1∑n​ωi​⋅xi​0 ω \omega ω是权重向量权…...

书生·浦语大模型实战营-学习笔记3

目录 (3)基于 InternLM 和 LangChain 搭建你的知识库1. 大模型开发范式&#xff08;RAG、Fine-tune&#xff09;RAG微调 &#xff08;传统自然语言处理的方法&#xff09; 2. LangChain简介&#xff08;RAG开发框架&#xff09;3. 构建向量数据库4. 搭建知识库助手5. Web Demo部…...

MySQL下对[库]的操作

目录 创建数据库 创建一个数据库案例&#xff1a; 字符集和校验规则&#xff1a; 默认字符集&#xff1a; 默认校验规则&#xff1a; 查看数据库支持的字符集&#xff1a; 查看数据库支持的字符集校验规则&#xff1a; 校验规则对数据库的影响&#xff1a; 操作数据…...

Django(七)

1.靓号管理 1.1 表结构 根据表结构的需求&#xff0c;在models.py中创建类&#xff08;由类生成数据库中的表&#xff09;。 class PrettyNum(models.Model):""" 靓号表 """mobile models.CharField(verbose_name"手机号", max_len…...

AT24C02读写操作 一

//AT24C02初始化 void AT24C02_Init(void) { IIC_Init(); } //AT24C02的字节写入 写一个字节 void AT24C02_WordWrite(uint8_Address,uint8_t Data) { //1。主机发送开始信号 IIC_StartSignal(); //2.主机发送器件地址 写操作 IIC_SentBytes(0xA0); //3.主机等侍从机应…...

.NET 8 中引入新的 IHostedLifecycleService 接口 实现定时任务

在这篇文章中&#xff0c;我们将了解 .NET 8 中为托管服务引入的一些新生命周期事件。请注意&#xff0c;这篇文章与 .NET 8 相关&#xff0c;在撰写本文时&#xff0c;.NET 8 目前处于预览状态。在 11 月 .NET 8 最终版本发布之前&#xff0c;类型和实现可能会发生变化。要继续…...

Redis--Geo指令的语法和使用场景举例(附近的人功能)

文章目录 前言Geo介绍Geo指令使用使用场景&#xff1a;附近的人参考文献 前言 Redis除了常见的五种数据类型之外&#xff0c;其实还有一些少见的数据结构&#xff0c;如Geo&#xff0c;HyperLogLog等。虽然它们少见&#xff0c;但是作用却不容小觑。本文将介绍Geo指令的语法和…...

127.0.0.1和0.0.0.0的区别

在网络开发中&#xff0c;经常会涉及到两个特殊的IP地址&#xff1a;127.0.0.1和0.0.0.0。这两者之间有一些关键的区别&#xff0c;本文将深入介绍它们的作用和用途。 127.0.0.1 127.0.0.1 是本地回环地址&#xff0c;通常称为 “localhost”。作用是让网络应用程序能够与本地…...

SpringBoot ES 聚合后多字段加减乘除

SpringBoot ES 聚合后多字段加减乘除 在SpringData Elasticsearch中&#xff0c;聚合统计的原理主要依赖于Elasticsearch本身的聚合框架。Elasticsearch提供了强大的聚合功能&#xff0c;使得你可以对文档进行各种计算和统计&#xff0c;从而得到有关数据集的有用信息。 Elast…...

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

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

【论文阅读】Deep Graph Contrastive Representation Learning

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

设计模式-简单工厂

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

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

在 Django 中&#xff0c;对象关系映射&#xff08;ORM&#xff09;提供了一种功能强大、表现力丰富的数据库交互方式。ORM 允许开发人员使用高级 Python 代码执行数据库查询&#xff0c;从而更轻松地处理数据库实体。 下面&#xff0c;我们将探讨 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具有高效性、原子性、支持多种数据结构、…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

GruntJS-前端自动化任务运行器从入门到实战

Grunt 完全指南&#xff1a;从入门到实战 一、Grunt 是什么&#xff1f; Grunt是一个基于 Node.js 的前端自动化任务运行器&#xff0c;主要用于自动化执行项目开发中重复性高的任务&#xff0c;例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

MySQL JOIN 表过多的优化思路

当 MySQL 查询涉及大量表 JOIN 时&#xff0c;性能会显著下降。以下是优化思路和简易实现方法&#xff1a; 一、核心优化思路 减少 JOIN 数量 数据冗余&#xff1a;添加必要的冗余字段&#xff08;如订单表直接存储用户名&#xff09;合并表&#xff1a;将频繁关联的小表合并成…...

【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)

LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 题目描述解题思路Java代码 题目描述 题目链接&#xff1a;LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...

【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案

目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后&#xff0c;迭代器会失效&#xff0c;因为顺序迭代器在内存中是连续存储的&#xff0c;元素删除后&#xff0c;后续元素会前移。 但一些场景中&#xff0c;我们又需要在执行删除操作…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...