react.js|React批处理原理及性能优化实践

事件循环 JavaScript是一门单线程语言,但是会分为同步和异步,同步任务和异步任务分别进入不同的执行"场所"。
同步任务进入主线程,异步任务进入Event Table并注册回调函数,Event Table会将这个函数移入任务队列(task queue),等待主线程的任务执行完毕。当执行栈中的代码执行完毕,执行栈(call stack)中的任务为空时,就会读取任务队列(task queue)中的任务,去执行对应的回调。如此循环,就形成js的事件循环机制(Event Loop)。
事件循环队列里有两种任务,宏任务(同步代码、setTimeout)、微任务(promise),一次事件循环中的同步代码执行完毕后,会去把队列中已有的微任务执行清空,然后进入下一次事件循环
先做几个题感受一下
react.js|React批处理原理及性能优化实践
文章图片
答案:13642 react.js|React批处理原理及性能优化实践
文章图片
答案:136542 react.js|React批处理原理及性能优化实践
文章图片
答案:135642 react.js|React批处理原理及性能优化实践
文章图片
答案:3 react.js|React批处理原理及性能优化实践
文章图片
答案:23 几个问题 setState到底是异步还是同步的?
熟悉react的小伙伴都知道,react是通过状态变化,然后自动计算,将这些变化渲染在界面上的。 但在实际使用过程中,有很多地方表现的与我们预期的不一致。我们来看下一个简单的demo。多个顺序执行的setState不是同步的一个个执行的,会一个个加入队列中,最后一期执行,即批处理『我不会爬到山峰三次,每一次都去更新一个状态』
React 会把我们更新 state 的函数加入到一个队列里面,然后,按照函数的顺序依次调用。同时,为每个函数传入 state 的前一个状态,这样,就能更合理的来更新我们的 state 了。
为什么直接修改this.state无效
要知道setState本质是通过一个队列机制实现state更新的。 执行setState时,会将需要更新的state合并后放入状态队列,而不会立刻更新state,队列机制可以批量更新state。 如果不通过setState而直接修改this.state,那么这个state不会放入状态队列中,下次调用setState时对状态队列进行合并时,会忽略之前直接被修改的state,这样我们就无法合并了,而且实际也没有把你想要的state更新上去。
React17的渲染流程源码解析(事件响应)
react.js|React批处理原理及性能优化实践
文章图片
onPress之后进入到React的事件代理和分发;重点关注一下batchedUpdates。
React的渲染流程源码解析(batchedUpdate)
react.js|React批处理原理及性能优化实践
文章图片
executionContext代表当前处于什么处理流程状态
BatchedContext是批处理状态
React的渲染流程源码解析(setState)
react.js|React批处理原理及性能优化实践
文章图片
this.setState进入的关键代码片段
【react.js|React批处理原理及性能优化实践】lane: 获取当前更新的类型(优先级)
保存状态的更新数据
进入调度方法看是否需要将更新应用到渲染
React的渲染流程源码解析(lane)
react.js|React批处理原理及性能优化实践
文章图片
fiber.mde: 当前React的虚拟dom的调度渲染模式
BlockingMode: 含有并发模式小部分功能的模式 ConcurrentMode:并发模式(React18的默认模式)
Reat17中不特意开启,就不会进入上述两个模式中
React的渲染流程源码解析(scheduleUpdateOnFiber 调度)
react.js|React批处理原理及性能优化实践
文章图片
lane: 当前这个更新的类型(优先级)
若当前更新不在批处理状态中
此方法约等于 直接渲染
React17默认模式的批处理是半自动的 事件处理函数、生命周期函数中的同步代码包裹在batchedUpdates的回调中,react框架就能知道所有的同步更新可以合并,到同步代码运行的最后前再做渲染。
如果放在异步代码里,框架内部的事件循环就结束了,无法控制后续异步回调里的更新做批处理,每次更新都会触发渲染。
那有没有全自动?
React18以及React17的并发模式的批处理是全自动的 Why?
对每一个更新操作定义优先级,在一段时间内优先级相同的更新只渲染一次
相关优化思路

  • 先级高的异步任务先处理,优先级低的异步任务等渲染完成再处理;* 方法内的setState、dispatch放入batch回调中处理,batch可以通过train_rn_common引入* * *
今天分享了公司React业务代码中在处理电商场景(日活2千万)一些性能优化操作,没有使用代码块,而是直接截图了 公司业务代码(隐藏了baseUrl),防止一些啥都不懂的前端小朋友误会~

    推荐阅读