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

React 19 竞态问题解决

竞态问题/竞态条件 指的是,当我们在交互过程中,由于各种原因导致同一个接口短时间之内连续发送请求,后发送的请求有可能先得到请求结果,从而导致数据渲染出现预期之外的错误。

因为防止重复执行可以有效的解决竞态问题,因此许多时候面试官也会直接在面试中问我们如何实现防重。常用的方式就是取消上一次请求,或者设置状态让按钮不能连续点击,想必各位大佬对这些方案都已经非常熟悉,我这里就不展开细说。

React 19 结合 Suspense 也在竞态问题上,提出了一个自己的解决方案。我们结合新的案例来探讨一下这个问题,看完之后大家感受一下这种方式是好是坏。

const getApi = async () => {const res = await fetch('https://api.chucknorris.io/jokes/random')return res.json()
}export default function Index() {const [api, setApi] = useState(null)const [list, setList] = useState([])function __clickToGetMessage() {setApi(getApi())}return (<div><div id='tips'>点击按钮新增一条数据,该数据从接口中获取</div><button onClick={__clickToGetMessage}>新增数据</button><div className="content"><div className="list">{list.map((item, index) => {return <div className='item' key={item}>{item}</div>})}</div><Suspense fallback={<div>loading...</div>}><Item api={api} setList={setList} /></Suspense></div></div>)
}const Item = ({api, setList}) => {const [show, setShow] = useState(true)const joke = api ? use(api) : {value: 'nothing'}useEffect(() => {if (!api) returnsetList((list) => {if (!list.includes(joke.value)) {return list.concat(joke.value)}return list})setShow(false)}, [])const __cls = show ? '_03_a_value show' : '_03_a_value'return (<div className={__cls}>{joke.value}</div>)
}

首先,多次点击会导致多次请求,因此数组中会新增大量的数据。

其次,由于请求太密集,那么点击的先后顺序,与请求成功的先后顺序不一致,因此列表中的顺序也会与点击顺序不同。「竞态问题」

那么我们来试着操作一下,看看该案例会有什么反应。演示结果如下,新增一条数据时,我连续点击了 10 次。

 

结果我们发现,点击期间,并没有新的数据渲染到页面上,一直是 loading 的状态。

再来看一下此时的请求情况。

请求的顺序被严格控制了:上一个请求请求成功之后,下一个请求才开始发生。此时是一个串行的请求过程。

react 19 使用这种思路解决了竞态问题。与此同时,反馈到数据上,虽然前面多次的请求已经成功,但是对于组件状态来说,这个中间过程中一直有请求在发生,此时 React 认为中间的请求产生的数据为无效数据。只会把最后一个请求成功的数据作为最终的返回结果。

 

很显然,仅从 UI 结果上来说,这样的处理方式确实是非常合理的,我们不需要过多的干涉数据的处理,非常的轻松。但问题是,每次请求都成功发生。

当我点击 10 次,就会有 10 次请求,由于使用串行的策略来解决竞态问题,导致最后一次的请求结果需要等待很长实践才会返回。这无疑极大的降低了开发体验。

和取消上一次的请求相比,无论是从体验上,还是从效率上来说,无疑都是更差的一种方案。

和以往的解决方案,如按钮点击后在请求结果回来之前禁用按钮点击,或取消上一次请求相比,体验要差一点。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 从入门到精通:网络基础详解
  • 在Pycharm中把jupyter notebook转换成md格式
  • java入门-java方法实现+案例
  • 软件架构之计算机网络
  • 【鸿蒙学习笔记】使用动画
  • Vue3框架搭建:vue+vite+pina+typescript
  • C++ Qt 自制开源科学计算器
  • 2023.2版IDEA复制配置修改端口增加一个当前运行服务的操作流程
  • cv::Mat 操作多维矩阵的思路
  • 快速响应需求:App路由动态化探索
  • 2024 年第十四届亚太数学建模竞赛(中文赛项)浅析
  • 【深度学习实战(44)】Anchor based and Anchor free(无锚VS有锚)
  • 鸿蒙笔记导航栏,路由,还有axios
  • Java基础概念
  • UDP通讯实现
  • 【知识碎片】第三方登录弹窗效果
  • CentOS学习笔记 - 12. Nginx搭建Centos7.5远程repo
  • Elasticsearch 参考指南(升级前重新索引)
  • HashMap剖析之内部结构
  • KMP算法及优化
  • Python学习之路13-记分
  • SQLServer之创建显式事务
  • storm drpc实例
  • ucore操作系统实验笔记 - 重新理解中断
  • Vue 重置组件到初始状态
  • vue.js框架原理浅析
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • Vue官网教程学习过程中值得记录的一些事情
  • Zepto.js源码学习之二
  • 程序员最讨厌的9句话,你可有补充?
  • 工作手记之html2canvas使用概述
  • 技术胖1-4季视频复习— (看视频笔记)
  • 视频flv转mp4最快的几种方法(就是不用格式工厂)
  • 思考 CSS 架构
  • 一道面试题引发的“血案”
  • 一起参Ember.js讨论、问答社区。
  • 字符串匹配基础上
  • 看到一个关于网页设计的文章分享过来!大家看看!
  • 2017年360最后一道编程题
  • ​LeetCode解法汇总2808. 使循环数组所有元素相等的最少秒数
  • ​Python 3 新特性:类型注解
  • ######## golang各章节终篇索引 ########
  • #Java第九次作业--输入输出流和文件操作
  • #控制台大学课堂点名问题_课堂随机点名
  • (4)Elastix图像配准:3D图像
  • (done) NLP “bag-of-words“ 方法 (带有二元分类和多元分类两个例子)词袋模型、BoW
  • (MATLAB)第五章-矩阵运算
  • (react踩过的坑)Antd Select(设置了labelInValue)在FormItem中initialValue的问题
  • (二)WCF的Binding模型
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (四)软件性能测试
  • (贪心) LeetCode 45. 跳跃游戏 II
  • (轉貼) 寄發紅帖基本原則(教育部禮儀司頒布) (雜項)
  • . ./ bash dash source 这五种执行shell脚本方式 区别
  • .aanva