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

嵌入式调光控制库:轻量级软启/渐变/记忆逻辑实现 调光控制是智能照明系统的核心基础功能,涉及亮度调节、人机交互与电气安全多重需求。其底层原理依赖于对相位角或PWM占空比的精确时序控制,并需融合软启动、渐变过渡、状态记忆等工程化逻辑。这类轻量级调光行为逻辑层,不直接操作硬件寄存器,而是以确定性、无动态内存、可配置的方式封装用户意图到目标亮度值(0–100%)的映射过程,显著提升产品鲁棒性与跨平台复用能力。广泛应用于TRIAC交流调光、LED直流PWM驱动及DALI/Matter等智能照明协议网关中,尤其适合资源受限的Cortex-M系列MCU和FreeRTO 阅读详情

resetChildExpirationTime


1 )概述

  • 在 completeUnitOfWork 当中,有一步比较重要的一个操作,就是重置 childExpirationTime
  • childExpirationTime 是非常重要的一个时间节点,它用来记录某一个节点的子树当中,目前优先级最高的那个更新
  • 整个应用的调度过程当中使用的都是root节点,在 scheduleWork 的时候,即便我们创建更新的那个节点,是我们写的某一个组件
  • 但最终要先找到那一个root节点,然后再把它放到调度队列当中,因为会有这样的一个情况的存在
  • 所以我们对于一个 reactApp 来说,它某一个节点下面可能是会存在非常多的一个子树的
  • 每棵子树它创建的不同的任务,它的 expirationTime 都会不一样的
  • 通过 childExpirationTime 来集中,最终可以在 root 上面能够快速的找到整个应用当中优先级最高的那个任务
  • 举个例子,假设同时在 Input 和 List 两个组件内都去创建了一个异步的更新,创建这个异步的更新的过程当中
  • 假设,Input的 ExpirationTime 优先级比较高,List 的 expirationTime 优先级比较少
  • 对于div节点来说,它记录的是Input节点的 expirationTime, 因为它的优先级比较高
  • 对于div来说,它如果下一个任务要去更新,它的优先级肯定是先更新 Input,而不会先更新 List
  • 对于 RootFiber 和 App来说,因为它们的child只有div, 所以它们记录的会是 div 上面指定的那个优先级最高的 expirationTime
  • 所以说 childExpirationTime 对于有分叉的点来说是非常重要的, 它可以记录不同的子树所创建的不同的更新
  • 如果我们的分叉变得越来越多,有非常多个的时候,那么用这种方式来记录它的效率明显是会是更高一点的
  • 对于这个情况下,如果我 Input 这个更新已经执行完了,它上面已经没有 expirationTime,因为它没有任务要去更新了
  • 对于div来说,这个时候如果它还是认为这个Input它之前的 expirationTime 是最高优先级的话,那就不对了,之后的更新可能就会有出现问题
  • 所以对于div这个节点,我们执行了 completeUnitOfWork 之后,要去更新它的 childExpirationTime
  • 对于每一个节点都是一样的, 在上述这个例子里面,特别重要的一点就是 div, div 要更新,那么它上面的节点都是要更新的
  • 因为它们之前记录的都是 div 记录的那个值,所以,它们执行 completeUnitOfWork 的时候,也都要去做相同的操作

2 )源码

定位到 packages/react-reconciler/src/ReactFiberScheduler.js#L989

对应到代码里面,来看在 completeUnitOfWork 里面,我们这边执行完了 completeWork
马上会执行 resetChildExpirationTime 那么这个方法它具体做了什么呢?

function resetChildExpirationTime(
  workInProgress: Fiber,
  renderTime: ExpirationTime,
) {
  // 首先判断 renderTime ,就是当前正在执行更新的那一个优先级对应的 expirationTime
  // 如果它不等于never,并且 workInProgress.childExpirationTime 等于 Never
  // 也就是说 workInProgress 就是我们当前节点的子节点优先级最高的那个任务是never
  // 就是永远不会更新到的并且我们现在也不是正在执行,never,就是永远不会更新到的那些节点的更新
  // 说明我们这边根本就不需要做任何的操作,所以我们直接return就可以了
  if (renderTime !== Never && workInProgress.childExpirationTime === Never) {
    // The children of this component are hidden. Don't bubble their
    // expiration times.
    return;
  }

  let newChildExpirationTime = NoWork;

  // Bubble up the earliest expiration time.
  // 跳过这个if, 直接到 else
  if (enableProfilerTimer && workInProgress.mode & ProfileMode) {
    // We're in profiling mode.
    // Let's use this same traversal to update the render durations.
    let actualDuration = workInProgress.actualDuration;
    let treeBaseDuration = workInProgress.selfBaseDuration;

    // When a fiber is cloned, its actualDuration is reset to 0.
    // This value will only be updated if work is done on the fiber (i.e. it doesn't bailout).
    // When work is done, it should bubble to the parent's actualDuration.
    // If the fiber has not been cloned though, (meaning no work was done),
    // Then this value will reflect the amount of time spent working on a previous render.
    // In that case it should not bubble.
    // We determine whether it was cloned by comparing the child pointer.
    const shouldBubbleActualDurations =
      workInProgress.alternate === null ||
      workInProgress.child !== workInProgress.alternate.child;

    let child = workInProgress.child;
    while (child !== null) {
      const childUpdateExpirationTime = child.expirationTime;
      const childChildExpirationTime = child.childExpirationTime;
      if (childUpdateExpirationTime > newChildExpirationTime) {
        newChildExpirationTime = childUpdateExpirationTime;
      }
      if (childChildExpirationTime > newChildExpirationTime) {
        newChildExpirationTime = childChildExpirationTime;
      }
      if (shouldBubbleActualDurations) {
        actualDuration += child.actualDuration;
      }
      treeBaseDuration += child.treeBaseDuration;
      child = child.sibling;
    }
    workInProgress.actualDuration = actualDuration;
    workInProgress.treeBaseDuration = treeBaseDuration;
  } else {
    // 这边主要是有一个 while循环, 这个while循环它首先使用的是 workInProgress.child
    // 它就是我们当前节点的child,然后获取child的 expirationTime 以及 childChildExpirationTime
    // child.expirationTime 是它自身它所创建的更新对应的 expirationTime
    // 而 child.childExpirationTime 是child的子树里面任何几个节点它所创建的更新所对应的优先级最高的 expirationTime
    let child = workInProgress.child;
    while (child !== null) {
      // 为什么这边要用这两个值?因为我们没有办法直接拿到当前节点它所有子树最高优先级的点
      // 只能是通过去遍历它的所有的第一层的子节点以及每个子节点它的 childExpirationTime
      // 因为我们这个 completeUnitOfWork 是由底往上去更新的一个过程
      // 那么由底往上更新的过程,就会每一个节点都会对应这个操作
      // 对应的这个操作之后,它肯定就是每一个节点都会更新到优先级最高的那个 expirationTime
      const childUpdateExpirationTime = child.expirationTime;
      const childChildExpirationTime = child.childExpirationTime;
      // 接下来进行判断更新
      if (childUpdateExpirationTime > newChildExpirationTime) {
        newChildExpirationTime = childUpdateExpirationTime;
      }
      if (childChildExpirationTime > newChildExpirationTime) {
        newChildExpirationTime = childChildExpirationTime;
      }
      // 下一个节点
      child = child.sibling;
    }
  }

  workInProgress.childExpirationTime = newChildExpirationTime;
}
  • 以上注释写在代码里,简单来说
    • 就是在每一次 complete 一个节点之后就要
    • 去重设它的 childExpirationTime 的一个过程
手把手教你学PCIE--所有 PF(Physical Function)共同管理和分配 VF 但具体如何分配和使用 VF 取决于硬件设计、驱动程序配置以及实际应用场景。 阅读详情

相关推荐

nnUnet代码解读--优化策略

优化策略 nnUNetTrainer def initialize_optimizer_and_scheduler(self): assert self.network is not None, "self.initialize_network must be called first" self.optimizer = torch.optim.Adam(self.network.parameters(), self.initial_lr, weight_decay=self.weight_

weixin_44858814的博客 3828

Fix signatures do not match the previously installed version

报错信息FAILURE: Build failed with an exception.* What went wrong: Execution failed for task ':app:installDebug'. > com.android.builder.testing.api.DeviceException: com.android.ddmlib.InstallException: Fai

Wang的专栏 2万+

遥感生态指数(RSEI)——四个指数的计算

遥感生态指数是在4个生态指数的基础上通过主成分变换得出的一个评价生态环境质量的指标。因此,第二部分就是要分别计算出这4个指数的值。 ①首先,是绿度指数的计算,一般用归一化植被指数(NDVI) NDVI=(NIR-Red)/(NIR+Red) 在Bandmath工具中输入NDVI计算公式 (float(b4-b3))/(b4+b3) 其中,b3、b4分别是红波段和近红外波段 ②其次,是湿度计算。 WET = c1B1 + c2B2 + c3B3...

qq_41978498的博客 9万+

在react中 实现 base64的图片转换成formdata格式并实现上传功能

如果不想要服务端实现处理base64格式的图片的转换,那么在浏览器端来实现,部分属于伪代码,仅作为开发参考,请勿直接拷贝使用

Wang的专栏 8836

KRC文件——编程中的重要文件

KRC文件是指KUKA机器人控制器(KUKA Robot Controller)所使用的文件格式。KUKA是一家知名的机器人制造商,其机器人控制器通过KRC文件来管理和执行机器人程序。KRC文件包含了机器人的运动指令、逻辑控制、传感器数据等信息,以及与机器人相关的配置参数。这些文件通常使用KRL(KUKA Robot Language)编写,是一种特定的编程语言。KRC文件具有扩展名为.krc的格式,可以在KUKA机器人控制器上直接加载和执行。

TechProX的博客 2972

快速解决gradle下载慢的问题的小技巧

在ionic run 或build 或clean命令的时候,如果没有下载过gradle, 需要重新下载一次,而通过CLI的方式下载很慢,即使科学上网后,下载还是存在一些问题。这里总结一下,快速的下载安装方式。 步骤 本地安装 http-server 包, 通过 $ npm i -g http-server 的方式安装到全局 在官网上下载自己的版本,目前自带的版本是 2.14.1,其他版本可能在执行过

Wang的专栏 6714

基于MATLAB开发AUTOSAR软件应用层模块-part2.建立一个AUTOSAR的模型,并生成autosar格式代码

上一篇我们建立了一个空模型,这篇我们接着上篇文章,建立一个简单的模型 点击 Library Browser,打开simulink模块库,见下图 左侧是模块库的列表,右侧是每个模块库里包含的具体的模块。 点击通用模块库,里边是一些常见的模块, 我们选取里边的3个模块,分别是输入,输出和增益三个模块,右键点击模块,选择add block to model xx,可以把模块添加到模型中。 然后练好连线 一个简单的模型就搭建好了,之后我们修改配置,将模型修改为AUT...

汽车软件开发 3304

React 实现 2D 画板功能

在移动端或者PC端我们来模拟画板的实现, 支持清除和导出功能,此处简单实现,仅作开发参考。 效果演示 主要代码演示 /* 此模块用于实现签名绘图功能 */ // 需要用到的变量定义 let clickX = new Array(); let clickY = new Array(); let clickDrag = new Array(); let paint; let point...

Wang的专栏 4325

vue3 - vite报错TypeError: crypto.hash is not a function(vue3+vite启动运行提示错误,项目无法启动且打包报错失败,详细解决排查方案教程)

vue3 vite 报错,vue3+vite启动报错:TypeError: crypto.hash is not a function,创建vue3+vite项目时报错TypeError: crypto.hash is not a function,如何解决这个问题,VUE3+VITE报错crypto.hash,vue3运行报错,vite运行报错,vue3打包报错,vite打包报错,vue3新建项目无法运行,vue3 vite创建项目直接报错了,node版本不兼容,修改了node版本还是不行,依旧报错,一直

✅ 精选推荐文章 1万+

AI智能体在化学中的伦理问题:7个案例,架构师如何应对?

AI在化学中的应用早已不是新鲜事:药物发现中用AI预测分子活性(比如AlphaFold预测蛋白质结构)、化工生产中用AI优化合成路线(降低成本30%+)、材料研发中用AI设计新型电池材料(缩短研发周期5年)……但随着AI从“辅助工具”升级为“自主决策智能体”(比如能自动调整反应条件的“化学机器人”),伦理风险开始从“潜在隐患”变成“真实事故”。AI在化学中会踩哪些伦理“坑”?(用案例具象化)这些“坑”的底层逻辑是什么?(从技术到价值观的链条)架构师能做什么?

AI 算法实战派 1364

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

对于在 beginWork 中的 context 操作,可以看上述判断成立的条件下的代码,即便有符合跳过更新的操作,依然 需要 push 和 pop 操作。如果我们可以跳出组件的更新,也就是代表着当前这个 classComponent,它的state它的props都应该是没有任何变化的。对于子组件来说,它的所有子树所获取到的context肯定是经过子组件,和上层的父组件合并的 context 了, 也就是。所以,先 push 一个老的值进去再说, 然后到后面,如果发现这个组件它是要更新的,就调用这个。

Wang的专栏 2803

嵌入式面试题精选100道及参考答案(4万字长文)

指针是C语言中一种特殊的变量,它存储的是另一个变量的内存地址。指针的使用提供了一种间接访问和操作内存的方法。地址操作:通过使用运算符,可以获取变量的地址,并将这个地址赋值给指针变量。间接引用:使用运算符可以访问指针指向的变量的值。动态内存分配:指针用于动态地分配和释放内存。数组操作:指针可以用于遍历和操作数组。函数参数:指针作为函数参数可以改变原始数据。字符串操作:在C语言中,字符串通常以字符数组的形式存在,并通过字符指针进行操作。// 指向数组的第一个元素i < 5;++i) {在这个例子中,

大模型大数据攻城狮的专栏 1974

Fix babel-preset-react-native TransformError

错误环境新版本存在不兼容,在运行 react-native run-android 的时候,发生的错误分析: babel-preset-react-native version : @3.0.0 $ react-native -v :react-native-cli: 2.0.1 react-native: 0.47.1$node -v : v7.8.0 $ npm -v :4.4.4 解决方案

Wang的专栏 2800

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

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

react的任务可以被打断,其实就是基于时间分片的,人眼最高能识别的帧数不超过30帧,电影的帧数差不多是在24,浏览器的帧率一般来说是60帧,也就是每秒60个画面, 平均一个画面大概是16.5毫秒左右,浏览器正常的工作流程是运算渲染,运算,渲染运算渲染,在浏览器里面一个运算,加上一个渲染就是一帧

Wang的专栏 2796

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

在react项目中修改webpack中本地服务器架设的目录

一个产品的上线往往会有很多的问题,现在就出现一个需求,我们是在服务器下的某个目录进行发布,而不是根服务器,服务端不想为一个项目配置ip地址,而在react项目中,默认是走的根路径,现在我们就开始修改一下它。 前提说明 如果我们需要修改手动配置webpack, 那么根据现在的版本, 我们只能执行 npm run eject, 之后就可以着手修改了。 webpack中与需求相关的...

Wang的专栏 2397

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

React18源码: React调度中的3种优先级类型和Lane的位运算

可以看得出来lane&-lane的结果是SyncLane,所以通过lane&-lane就能分离出最高优先级的任务。即A(cpu)>B(IO)>C(cpu).此时的需求需要将任务B从group中分离出来,先处理cpu任务A和C。在新版本的React中,还有一个新特性,就是render阶段可能被中断,在这个期间会产生一个更高优先级的任务。如上就是通过 lanes & -lanes 分离出最高优先级的任务的,我们来看一下具体的流程。也即是说lane的代表的数值越小,此次更新的优先级就越大。

Wang的专栏 2394

React18原理: 核心包结构与两大工作循环

react中的工作循环,这是它的一个最顶层的一个流程图,在这张图里面,有两个核心的大循环,第一大循环是 react-reconciler 提供的,它的核心是构建fiber树,生成任务,第二大循环是 scheduler 提供的, 它的核心是任务调度(处理任务的优先级),react的原理实际上就是两大工作循环

Wang的专栏 2356

React18原理: 生命周期中特别注意事项

生命周期就是一个组件从诞生到销毁的全过程(包含错误捕获,这里暂且不聊这个)react 在组件的生命周期中注册了一系列的钩子函数支持开发者在其中嵌入代码,并在适当的时机运行生命周期本质上就是组件中的钩子函数,主要有三个主要的钩子挂载更新卸载。

Wang的专栏 2244

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

定位到 packages/react-reconciler/src/ReactFiberBeginWork.js。整个文件 export 出去的只有 beginWork 方法。

Wang的专栏 2140

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

在更新了一个节点之后,拿到它的props.children, 要根据这个children里面的 ReactElement 来去创建子树的所有的 fiber 对象, 要根据 props.children 来生成 fiber 子树,然后判断 fiber 对象它是否是可以复用的

Wang的专栏 2133

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

各种不同类型组件的一个更新过程对应的是在执行 `performUnitOfWork` 里面 `beginWork` 阶段,它是去向下遍历一棵 fiber 树的一侧的子节点,然后遍历到叶子节点为止,以及 return 自己 child 的这种方式

Wang的专栏 2088

React18原理: 渲染与更新时的重点关注事项

react 在渲染过程中要做很多事情,所以不可能直接通过初始元素直接渲染还需要一个东西,就是虚拟节点,暂不涉及React Fiber的概念,将vDom树和Fiber 树统称为虚拟节点有了初始元素后,React 就会根据初始元素和其他可以生成虚拟节点的东西生成虚拟节点React一定是通过虚拟节点来进行渲染的对于首次挂载阶段需要了解React的渲染流程通过书写的初始元素和一些其他可以生成虚拟节点的东西来生成虚拟节点然后针对不同的节点类型去做不同的事情,最终将真实DOM挂载到页面上。

Wang的专栏 2069

21st.dev 上手教程:12000+ React 组件库怎么用,6 步从挑样式到接进 Cursor

21st.dev 收录 12000+ 个 React + Tailwind 组件、297 套整站模板与 979 套主题。本文是手把手流程版:按页面用途找组件、用复制或 shadcn CLI 落地、接入 MCP 让 Cursor 自己取代码、用整站模板开局,附 10 张真实组件截图和 4 个常见坑。

懿轩的技术小窝 232

成为全栈·Vue 管理后台篇·Naive UI 主题对齐:React 后台配色与明暗模式

本文根据 React 管理后台的蓝紫主色与浅/深色语义令牌,分析 Vue 后台如何用 CSS custom properties、Naive UI `NConfigProvider`、theme overrides、Pinia UI store 和系统媒体查询完成主题对齐。文章说明 CSS class 与 Naive UI darkTheme 必须同步,Markdown 编辑器/预览需要单独接入 resolvedTheme,并通过主题/侧栏持久化区分非敏感偏好与认证凭证。

FungLeo's Blog 273

手搓 AI Agent 02:让模型第一次“动手“——Agent Loop 与 ReAct

本系列第2篇实现Agent核心循环——ReAct模式,让模型从“被动回答”变为“主动执行”。通过LLMClient工具调用能力,构建think → act → observe闭环,首次实现模型自主调用计算器、读取结果并继续推理。代码支持安全算术、步数限制与错误隔离,升级终端REPL为可观察的智能体交互界面。每步操作清晰可见,为后续多工具、规划与协作打下基础。

快乐来自程序里 131
上一篇: React16源码: React中的completeUnitOfWork的源码实现
下一篇: React16源码: React中的completeWork中对不同类型节点处理的源码实现
Wang's Blog
博客等级 码龄12年 7438粉丝 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、付费专栏及课程。

余额充值