React Scheduler
的原理是什么,真是太简单了!根本不是你想的什么高大上的东西,50字内给你解释完。
🤖 原理
-
根据你传入的不同优先级创建不同过期时间的任务,根据过期时间大小放到任务队列小顶堆里面。
-
通过
messageChannel
安排一个宏任务执行while
循环-
拿到堆顶的任务,如果没过期或者超过 5ms 退出本次工作循环,重新安排一个宏任务,在下一帧执行。
-
如果过期了就开始执行这个任务,
-
如果任务没有返回值,这个任务就从堆中去掉,然后再拿一个堆顶的任务来执行
-
如果这个函数的返回值是一个函数,就退出本次的循环,这个任务保留,重新开始调度一个新的循环。
-
-
看到这里,你已经掌握 Scheduler
原理了
🚀 小贴士:小顶堆是什么?
1. 简单的扣胩,就是一棵二叉树,父节点和左右节点中,父节点永远是最小的
2. 也就是说,树顶部的节点永远是最小的,也是就是最早过期的
🤖 scheduler
在 react
中有什么用呢?
🚀 小例子:先看看这个例子
js
function App() {
const [name, setName] = useState('许泽川')
return name
}
当我们 setName('刘德华')
在做什么呢?
- 其实就是创建了一个更新帮我把许泽川变成刘德华,然后触发了一个带有优先级的重渲染任务
- 然后呢,
scheduler
就会根据这个优先级安排微任务或者宏任务来执行这个重渲染 - 等一下重渲染到
App
组件,其实就是重新执行 Ap
p 函数,重新执行useState('许泽川')
在里面应用这个更新帮我把许泽川变成刘德华 到name
上,这时候拿到name
就是刘德华
了
🚀 小知识:优先级是什么?
优先级不懂的先看上面文章,不然下面的原理看不懂,顺便帮我涨涨点击率 🥰
🚀 scheduler
的用处来喽 😤
- 文章里提到 每次
setState
会判断当前上下文拿一个车道出来,创建一个车道对应优先级的更新,和对应优先级的重渲染任务来处理这个更新 - 文章里面还提到 连续事件默认事件空闲事件全部通过宏任务
MessageChannel
执行重渲染任务 补充一点,就是通过schduler
来安排宏任务的
js
const `优先级` = `连续事件优先级 or 默认事件优先级 or 空闲事件优先级`
scheduler(`优先级`, `setState 对应的重渲染任务`)
- 在
useTransition
这个上下文里面setState
,他就会申请到一个transition
车道,对应的是空闲事件优先级。那么setState
安排的重渲染任务他是通过宏任务执行。并且他的优先级是最低,是最不重要的,会开启一个叫做时间切片
的东西。
时间切片就是说,setState
安排的重渲染任务变成了可中断的每 5ms
停止执行,看下图
js
function `setState 对应的重渲染任务`() {
while (执行超过5ms了) {
重渲染一个 `fiber`
`performUnitOfWork`();
}
if (所有的 fiber 还没渲染完) {
return `setState 对应的重渲染任务`
}
}
- 你看上面的代码,超过
5ms
退出循环后干了什么?返回了这个函数他本身。
返回的这个函数本身
setState 对应的重渲染任务
有什么用?上面我已经把全部原理讲完了,我给一点提示,你们重新看一下文章对应的部分应该就懂了
记不记得上面提到过的,
scheduler
(优先级
,setState 对应的重渲染任务
)记不记得上面提到过的,在
scheduler
内部,如果这个函数的返回值是一个函数,就退出本次的循环,这个任务保留,重新开始调度一个新的循环
🤖 相关
跟我一样看过源码的人,可能你可能会出现一个疑问?
当前
fiber
暂停渲染后,再次恢复执行,到底是从头开始重渲染,还是从当前的fiber
开始重渲染。通过我长期的观察,我找到了真相。又能水一篇文章🥰
面试官:你说你做过组件库,肯定了解过复杂组件状态管理的useSyncExternalStore吧?我:😭面试官:你跟我说 setState 是同步的,它不是异步的吗?背错面试题了吧你!我:😭
面试官:你说你开发过组件库,那你怎么会不知道受控组件?面试就到这里吧。我:😭
版权归许泽川所有如需转载,请提前询问本人的许可