面试官:听说你精通 React 源码,那你讲讲 Scheduler 调度器。我:😭

React Scheduler 的原理是什么,真是太简单了!根本不是你想的什么高大上的东西,50字内给你解释完。

🤖 原理

  1. 根据你传入的不同优先级创建不同过期时间的任务,根据过期时间大小放到任务队列小顶堆里面。

  2. 通过 messageChannel 安排一个宏任务执行 while 循环

    1. 拿到堆顶的任务,如果没过期或者超过 5ms 退出本次工作循环,重新安排一个宏任务,在下一帧执行。

    2. 如果过期了就开始执行这个任务,

      1. 如果任务没有返回值,这个任务就从堆中去掉,然后再拿一个堆顶的任务来执行

      2. 如果这个函数的返回值是一个函数,就退出本次的循环,这个任务保留,重新开始调度一个新的循环。

看到这里,你已经掌握 Scheduler 原理了

🚀 小贴士:小顶堆是什么?

1. 简单的扣胩,就是一棵二叉树,父节点和左右节点中,父节点永远是最小的

2. 也就是说,树顶部的节点永远是最小的,也是就是最早过期的

🤖 schedulerreact 中有什么用呢?

🚀 小例子:先看看这个例子

js 复制代码
function App() {
  const [name, setName] = useState('许泽川')
  
  return name
}

当我们 setName('刘德华') 在做什么呢?

  1. 其实就是创建了一个更新帮我把许泽川变成刘德华,然后触发了一个带有优先级的重渲染任务
  2. 然后呢,scheduler 就会根据这个优先级安排微任务或者宏任务来执行这个重渲染
  3. 等一下重渲染到 App 组件,其实就是重新执行 App 函数,重新执行 useState('许泽川') 在里面应用这个更新帮我把许泽川变成刘德华name 上,这时候拿到 name 就是 刘德华

🚀 小知识:优先级是什么?

点我这里,我告诉你优先级是什么 🥰

优先级不懂的先看上面文章,不然下面的原理看不懂,顺便帮我涨涨点击率 🥰

🚀 scheduler 的用处来喽 😤

  1. 文章里提到 每次 setState 会判断当前上下文拿一个车道出来,创建一个车道对应优先级的更新,和对应优先级的重渲染任务来处理这个更新
  2. 文章里面还提到 连续事件默认事件空闲事件全部通过宏任务 MessageChannel执行重渲染任务 补充一点,就是通过 schduler 来安排宏任务的
js 复制代码
const `优先级` = `连续事件优先级 or 默认事件优先级 or 空闲事件优先级`
scheduler(`优先级`, `setState 对应的重渲染任务`)
  1. useTransition 这个上下文里面 setState,他就会申请到一个 transition 车道,对应的是空闲事件优先级。那么 setState 安排的重渲染任务他是通过宏任务执行。并且他的优先级是最低,是最不重要的,会开启一个叫做 时间切片 的东西。

时间切片就是说,setState 安排的重渲染任务变成了可中断的每 5ms 停止执行,看下图

js 复制代码
function `setState 对应的重渲染任务`() {
  while (执行超过5ms了) {
    重渲染一个 `fiber`
    `performUnitOfWork`(); 
  }
  if (所有的 fiber 还没渲染完) {
    return `setState 对应的重渲染任务`
  }
}
  1. 你看上面的代码,超过 5ms 退出循环后干了什么?返回了这个函数他本身。

返回的这个函数本身 setState 对应的重渲染任务有什么用?

上面我已经把全部原理讲完了,我给一点提示,你们重新看一下文章对应的部分应该就懂了

  1. 记不记得上面提到过的, scheduler(优先级, setState 对应的重渲染任务)

  2. 记不记得上面提到过的,在 scheduler 内部,如果这个函数的返回值是一个函数,就退出本次的循环,这个任务保留,重新开始调度一个新的循环

🤖 相关

跟我一样看过源码的人,可能你可能会出现一个疑问?

当前 fiber 暂停渲染后,再次恢复执行,到底是从头开始重渲染,还是从当前的 fiber 开始重渲染。通过我长期的观察,我找到了真相。

又能水一篇文章🥰
面试官:你说你做过组件库,肯定了解过复杂组件状态管理的useSyncExternalStore吧?我:😭

面试官:你跟我说 setState 是同步的,它不是异步的吗?背错面试题了吧你!我:😭

面试官:你说你开发过组件库,那你怎么会不知道受控组件?面试就到这里吧。我:😭
版权归许泽川所有

如需转载,请提前询问本人的许可

相关推荐
码事漫谈18 分钟前
解决 Anki 启动器下载错误的完整指南
前端
im_AMBER38 分钟前
Web 开发 27
前端·javascript·笔记·后端·学习·web
聪明的笨猪猪1 小时前
Java Redis “缓存设计”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
蓝胖子的多啦A梦1 小时前
低版本Chrome导致弹框无法滚动的解决方案
前端·css·html·chrome浏览器·版本不同造成问题·弹框页面无法滚动
玩代码1 小时前
vue项目安装chromedriver超时解决办法
前端·javascript·vue.js
訾博ZiBo1 小时前
React 状态管理中的循环更新陷阱与解决方案
前端
StarPrayers.2 小时前
旅行商问题(TSP)(2)(heuristics.py)(TSP 的两种贪心启发式算法实现)
前端·人工智能·python·算法·pycharm·启发式算法
聪明的笨猪猪2 小时前
Java Redis “运维”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
一壶浊酒..2 小时前
ajax局部更新
前端·ajax·okhttp
苏打水com2 小时前
JavaScript 面试题标准答案模板(对应前文核心考点)
javascript·面试