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

React18源码: schedule任务调度messageChannel

React调度原理(scheduler)

  • 在React运行时中,调度中心(位于scheduler包)
  • 是整个React运行时的中枢(其实是心脏),所以理解了scheduler调度,就基本掌握了React的核心
  • React两大循环:从宏观的角度介绍 React 体系中两个重要的循环,其中任务调度循环就是本文的主角
  • Reconciler 运行流程从宏观的角度描述了 react-reconciler 包的核心作用
    • 并把 reconciler 分为了4个阶段
    • 其中第 2 个阶段注册调度任务串联了 scheduler 包和 react-reconciler 包
    • 其实就是任务调度循环中的一个任务(task)
  • 优先级管理
    • React体系中的3中优先级的管理
    • 着重源码中react-reconciler与scheduler包中关于优先级的转换思路
    • 其中 SchedulerPriority 控制任务调度循环中循环的顺序

调度实现

调度中心最核心的代码,在 SchedulerHostConfig.default.js 中

内核

  • 该js文件一共导出了8个函数,最核心的逻辑,就集中在了这8个函数中
    export let requestHostCallback; // 请求及时回调: port.postMessage
    export let cancelHostCallback; // 取消及时回调: scheduledHostCallback = null
    export let requestHostTimeout; // 请求延时回调: setTimeout
    export let cancelHostTimeout; // 取消延时回调: cancelTimeout
    export let shouldYieldToHost; // 是否让出主线程 (currentTime >- deadline && needsPaint):
    export let requestPaint; // 请求绘:设置 needsPaint = true
    export let getCurrentTime; // 获取当前间
    export let forceFrameRate; // 强制设置 yieldIntervol (让出主线程的周期)
    
  • react可以在nodejs环境中使用,所以在不同的js执行环境中,这些函数的实现会有区别
  • 下面基于普通浏览器环境,对这8个函数逐一分析

1 )调度相关:请求或取消调度

  • requestHostCallback

  • cancelHostCallback

  • requestHostTimeout

  • cancelHostTimeout

  • 这4个函数源码很简洁,非常好理解,它们的目的就是请求执行(或取消)回调函数

  • 现在重点介绍其中的及时回调 (延时回调的2个函数暂时属于保留api,17.0.2版本其实没有用上)

    // MessageChannel
    const performWorkUntilDeadline=() => {//...省略无关代码if (scheduledHostCallback !== null) {const currentTime = getCurrentTime();// 更新 deadlinedeadline = currentTime + yieldInterval;// 执行 callbackscheduledHostCallback(hasTimeRemaining, currentTime);} else {isMessageLoopRunning = false;};
    };const channel = new MessageChannel();
    const port = channel.port2;
    channel.port1.onmessage = performWorkUntilDeadline;// 请求回调
    requestHostCallback = function(callback) {// 1.保存callbackscheduledHostCallback = callback;if(!isMessageLoopRunning) {isMessageLoopRunning= true;// 2.通过 MessageChannel消息port.postMessage(null);}
    };// 取消回调
    cancelHostCallback = function() {scheduledHostCallback = null;
    }
    
  • 很明显,请求回调之后 scheduledHostCallback = callback

  • 然后通过MessageChannel发消息的方式触发performWorkUntilDeadline函数

  • 最后执行回调 scheduledHostCallback

  • 此处需要注意

    • MessageChannel在浏览器事件循环中属于宏任务
    • 所以调度中心永远是异步执行回调函数

2 )时间切片(timeslicing)相关:

  • 执行时间分割,让出主线程

  • 把控制权归还浏览器,浏览器可以处理用户输入,UI绘制等紧急任务

  • getCurrentTime: 获取当前时间

  • shouldYieldToHost: 是否让出主线程

  • requestPaint: 请求绘制

  • forceFrameRate: 强制设置yieldInterval(从源码中的引用来看,算一个保留函数,其他地方没有用到)

    const localPerformance = performance;
    // 获取当前时间
    getCurrentTime = () => localPerformance.now();// 时间切片周期,默认是5ms(如果一个task运行超过该周期,下一个task执行之前,会把控制权归还浏览器)
    let yieldInterval = 5;
    let deadline = 0;
    const maxYieldInterval = 300;
    let needsPaint = false;
    const scheduling = navigator.scheduling;
    // 是否让出主线程
    shouldYieldToHost = function() {const currentTime = getCurrentTime();if (currentTime >= deadline) {if (needsPaint || scheduling.isInputPending()) {// There is either a pending paint or a pending input.return true;}// There's no pending input. Only yield if we've reached the max// yield interval.return currentTime >= maxYieldInterval; // 在持续运行的react应用中, currentTime肯定大于300ms} else {// There's still time left in the frame.return false;}
    };// 请求绘制
    requestPaint = function() {needsPaint = true;
    };// 设置时间切片的周期
    forceFrameRate = function(fps) {if (fps < 0 || fps > 125) {// Using console['error'] to evade Babel and ESLintconsole['error']('forceFrameRate takes a positive int between 0 and 125, ' +'forcing frame rates higher than 125 fps is not supported',);return;}if (fps > 0) {yieldInterval = Math.floor(1000 / fps);} else {// reset the framerateyieldInterval = 5;};
    }
    
  • 这4个函数代码都很简洁,其功能在注释中都有解释.

  • 注意 shouldYieldToHost 的判定条件:

    • currentTime >= deadline: 只有时间超过 deadline 之后才会让出主线程
    • 其中 deadline = currentTime + yieldInterval
      • yieldInterval 默认是5ms, 只能通过 forceFrameRate 函数来修改
      • 如果一个task运行时间超过5ms,下一个task执行之前,会把控制权归还浏览器
  • navigator.scheduling.isInputPending():

    • 这facebook官方贡献给 Chromium 的api,现在已经列入W3C标准
    • 用于判断是否有输入事件(包括:input框输入事件,点击事件等).
  • 看完这8个内部函数,最后浏览一下完整的 performWorkUntilDeadline 回调的实现

    const performWorkUntilDeadline = () => {if(scheduledHostCallback !== null) {const currentTime = getCurrentTime(); //1.获取当前时间deadline = currentTime + yieldInterval; //2.  置deadline 当前时间 + 5ms, 也就是5ms超时const hasTimeRemaining = true;try {//  3.执行回调,返回是否有还有剩余任务const hasMoreWork = scheduledHostCallback(hasTimeRemaining, currentTime);if (!hasMoreWork) {// 没有剩余任务,退出isMessageLoopRunning = false;scheduledHostCallback = null;} else {port.postMessage(null); // 有剩余任务,发起新的调度}} catch (error) {port.postMessage(null); // 如有异常,重新发起调度throw error;}} else {isMessageLoopRunning = false;}needsPaint = false; // 重置开关
    }
    
  • 核心总结,如下图

  • MessageChanel 里面是宏任务异步执行
  • 在执行的过程中,基于 performWorkUnitlDeadline
  • 这个方法在执行任务过程中,有一个变量 hasMoreWork
  • 基于这个变量判断是否还有任务,如果还有,则继续往里面注册回调,没有则退出

相关文章:

React18源码: schedule任务调度messageChannel

React调度原理(scheduler) 在React运行时中&#xff0c;调度中心&#xff08;位于scheduler包&#xff09;是整个React运行时的中枢&#xff08;其实是心脏&#xff09;&#xff0c;所以理解了scheduler调度&#xff0c;就基本掌握了React的核心React两大循环&#xff1a;从宏…...

Jmeter 学习目录

Jmeter 所有内容均以学习为主输出内容&#xff0c;按照最小单位和基础进行输出。 如果有看不懂&#xff0c;或者有不明确的内容&#xff0c;欢迎大家留言说明。 Jmeter系列&#xff08;1&#xff09;Mac Jmeter下载安装启动 Jmeter系列&#xff08;2&#xff09;Jmeter 目录介…...

计算机网络 数据链路层课后题

1.以太网帧有哪些不同的封装格式&#xff1f;他们有何区别和应用场景&#xff1f; 以太网II封装&#xff08;Ethernet II&#xff09;&#xff1a;以太网II封装是最常用的以太网封装格式&#xff0c;也被称为DIX封装。它在数据链路层首部使用6个字节的目的MAC地址和6个字节的源…...

实现验证码功能

Kaptcha 文章目录 Kaptcha介绍插件使用介绍原理引入依赖生成验证码 验证码小项目初始化前端代码约定前后端交互接口接口定义 介绍 Kaptcha 是Google的⼀个⾼度可配置的实⽤验证码⽣成⼯具 https://code.google.com/archive/p/kaptcha ⽹上有很多⼈甚⾄公司基于Google的kaptc…...

PyQt6的开发流程(密码生成小程序为例)

PyQt6的开发流程&#xff08;密码生成小程序为例&#xff09; 文章目录 PyQt6的开发流程&#xff08;密码生成小程序为例&#xff09;一、流程介绍与概览1. 界面与逻辑分离的开发流程2. PyQt6的开发流程 二、打开 designer.exe 创建文件三、用QT设计师绘制界面保存成ui1. QT常用…...

思腾云计算中心 | 5千平米超大空间,基础设施完善,提供裸金属GPU算力租赁业务

2021年&#xff0c;思腾合力全资收购包头市易慧信息科技有限公司&#xff0c;正式开启云计算业务。思腾云计算中心占地2400平米&#xff0c;位于包头市稀土高新区&#xff0c;毗邻多家知名企业&#xff0c;地理位置优越&#xff0c;交通便利&#xff0c;是区内重要的信息化产业…...

【Leetcode每日一题】二分查找 - 在排序数组中查找元素的第一个和最后一个位置(难度⭐⭐)(18)

1. 题目解析 Leetcode链接&#xff1a;34. 在排序数组中查找元素的第一个和最后一个位置 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 核心在于找到给定目标值所在的数组下标区间&#xff0c;设计一个O(logn)的算法。 2. 算法原…...

远程连接 vscode 出错 “远程主机可能不符合 glibc 和 libstdc++ VS Code 服务器的先决条件”

原因&#xff1a; vscode 版本是 1.86&#xff0c;服务器上的 glibc 和 libstdc 版本不满足 要求(2.28 和 3.4.25)。 解决&#xff1a; 1、下载 1.85.2&#xff0c;解压直接运行 Code.exe。 2、回退 Remote-ssh 到 0.107.1。 参考&#xff1a; vscode 1.86版本远程ssh不兼容旧…...

Maven入门:Java项目构建和管理的利器

Maven入门&#xff1a;Java项目构建和管理的利器 Maven 是一个项目管理和综合工具&#xff0c;它基于项目对象模型&#xff08;POM&#xff09;概念。Maven 可以管理项目的构建、报告和文档。以下是一篇介绍 Maven 配置和应用的教程文章。 Maven简介 Maven 使用其核心概念 POM…...

《游戏引擎架构》 -- 学习4

资源及文件系统 文件系统 游戏引擎的文件系统API通常提供以下功能&#xff1a; 搜需路径&#xff1a;是含一串路径的字符串&#xff0c;各路径之间以特殊字符&#xff08;如冒号或分号&#xff09;分隔&#xff0c;找文件时就会从这些路径进行搜寻。例如在命令行下执行程序&a…...

Wagtail安装运行并结合内网穿透实现公网访问本地网站界面

文章目录 前言1. 安装并运行Wagtail1.1 创建并激活虚拟环境 2. 安装cpolar内网穿透工具3. 实现Wagtail公网访问4. 固定的Wagtail公网地址 正文开始前给大家推荐个网站&#xff0c;前些天发现了一个巨牛的 人工智能学习网站&#xff0c; 通俗易懂&#xff0c;风趣幽默&#xf…...

10分钟快速开始SkyWalking结合Springboot项目

10分钟快速开始SkyWalking结合Springboot项目 实习期间&#xff0c;公司让我去学习一下链路追踪如何集成到Springboot项目中。 为此有两个方案&#xff1a; 1.opentelementryjaegerprometheus opentelementry 收集器收集线上的metrics和traces&#xff0c;然后发送给jaeger和p…...

STM32—触摸键

目录 1 、 电路构成及原理图 2 、编写实现代码 3、代码讲解 4、烧录到开发板调试、验证代码 5、检验效果 此笔记基于朗峰 STM32F103 系列全集成开发板的记录。 1 、 电路构成及原理图 触摸键简单的了解就是一次电容的充放电过程。从原理图可以看出&#xff0c;触摸键 …...

python中字典(dict)原理及其操作

原理 Python中的字典&#xff08;Dictionary&#xff09;是一种基于哈希表&#xff08;Hash Table&#xff09;的实现&#xff0c;提供了高效的键值对&#xff08;Key-Value Pair&#xff09;存储和访问机制。了解字典的工作原理有助于更好地理解其性能特性以及为什么在某些情…...

​​​​​​​​​​​​​​.NET Core Web API实现微服务集群部署

​​​​​​​.NET Core Web API实现微服务集群部署 在.NET Core Web API中实现微服务集群部署通常涉及多个步骤&#xff0c;包括服务拆分、容器化、服务注册与发现、负载均衡等。以下是一个简化的步骤指南&#xff0c;用于在.NET Core中构建和部署微服务集群&#xff1a; 服…...

网络安全与信创产业发展:构建数字时代的护城河

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua&#xff0c;在这里我会分享我的知识和经验。&#x…...

外包干了3个月,技术倒退1年。。。

先说情况&#xff0c;大专毕业&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近6年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&#xf…...

Unity发布webgl获取浏览器的URL

Unity发布webgl获取浏览器的URL Unity发布webgl之后获取浏览器的url 在unity中创建文件夹Plugins&#xff0c;然后添加添加文件UnityGetBrowserURL.jslib var GetUrlFunc {//获取地址栏的URLStringReturnValueFunction: function () {var returnStr window.top.location.hre…...

StarRocks实战——多维分析场景与落地实践

目录 一、OLAP 系统历史背景 1.1 历史背景与痛点 1.2 组件诉求 二、StarRocks 的特点和优势 2.1 极致的查询性能 2.2 丰富的导入方式 2.3 StarRocks 的优势特点 三、多维分析的运用场景 3.1 实时计算场景 / 家长监控中心 3.2 实时更新模型选择 3.2.1 更新模型UNIQU…...

golang 函数式编程库samber/mo使用: Result

golang 函数式编程库samber/mo使用&#xff1a; Result 如果您不了解samber/mo库&#xff0c; 请先阅读上一篇 Option &#xff0c; 这篇讲述结构体Result的使用 Result和Option区别 samber/mo有了Option&#xff0c; 为什么还有Result呢? 我们先看看定义&#xff1a; Opt…...

KubeSphere 容器平台高可用:环境搭建与可视化操作指南

Linux_k8s篇 欢迎来到Linux的世界&#xff0c;看笔记好好学多敲多打&#xff0c;每个人都是大神&#xff01; 题目&#xff1a;KubeSphere 容器平台高可用&#xff1a;环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践

6月5日&#xff0c;2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席&#xff0c;并作《智能体在安全领域的应用实践》主题演讲&#xff0c;分享了在智能体在安全领域的突破性实践。他指出&#xff0c;百度通过将安全能力…...

OPENCV形态学基础之二腐蚀

一.腐蚀的原理 (图1) 数学表达式&#xff1a;dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一&#xff0c;腐蚀跟膨胀属于反向操作&#xff0c;膨胀是把图像图像变大&#xff0c;而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...