# 调度与时间片

Scheduler 调度 Reconciler 调和

# 一、前言

GUI渲染线程和JS引擎线程是项目排斥的,比如开发者用js写了一个遍历大量数据的循环,在执行js时候,会阻塞 浏览器的渲染绘制,给用户直观的感受就是卡顿。

# 二、何为异步调度

# 为什么采用异步调度

v15版本的React在应用上也存在着,一次更新,递归遍历大量的虚拟dom,造成占用了js线程,使得浏览器没有时间 去做一些动画效果,伴随着项目越来越大,项目越来越卡。

如何解决这个问题呢,首先对比一下vue框架,vue框架有template模版收集依赖的过程,轻松构建响应式,使得在 一次更新中,vue能够迅速相应,找到需要更新的范围,然后以组件粒度更新节点,渲染视图。但是在React中, 一次更新React无法知道更新的波及范围,所以react选择从根节点开始diff,查找不同,更新这些不同。

React似乎无法打破从root开始找不同的命运,但是还是要解决浏览器卡顿问题,那怎么办,解铃还须系铃人, 既然更新过程阻塞了浏览器的绘制,那么把React的更新,交给浏览器自己控制不就可以了嘛,如果浏览器有绘制 任务那么执行绘制任务,在空闲时间执行更新任务,就能解决卡顿问题了。与vue更快响应,更精确的更新范围, React选择更好的用户体验。

# 时间分片

React如何让浏览器控制React更新呢,首先浏览器每次执行一次事件循环(一帧)都会做如下事情, 处理事件,执行js,调用requestAnimation,布局Layout,绘制paint,在一帧执行后,如果没有其他事件,那么 浏览器会进入休息时间,那么有的一些不是那么特别紧急React更新,就可以执行了。

那么怎么知道浏览器有空闲时间呢? requestIdCallback(callback, {timeout})是谷歌浏览器提供的一个API,在浏览器有空余的时间,浏览器 就会调用requestIdCallback的回调。

  • callback回调,浏览器空余时间执行回调函数。
  • timeout超过时间。如果浏览器长时间没有空闲,那么回调就不会执行,为了解决这个问题,就有了timeout参数。

# 模拟requestIdleCallback

# 三、异步调度原理

# ScheduleCallback

# requestHostTimeout

# handleTimeout

# advanceTimers

# flushWork和workloop

# shouldYield 中止 workloop

# 四、总结

  • 异步调用的原理是什么
  • React为什么不用setTimeout
  • 时间分片是什么
  • React如何模拟requestIdleCallback
  • 简述一下调度流程
Last Updated: 9/12/2021, 8:50:43 PM