我正在参与掘金创作者训练营第4期,点击了解活动详情,一起学习吧!
想了解react任务调度参考react源码的scheduler
读完文章可以了解到:
- react执行的任务是什么?
- 通过比较什么来进行任务调度?
- 任务执行的先后顺序使用的算法是什么?
在第一篇mini-react构建fiber文章中我们了解到,通过window.requestIdleCallback()这个函数利用浏览器空闲时间来调用workLoop()执行构建和渲染的,下面我们将通过自己写的一个,将workLoop放进任务调度器中执行.requestIdleCallback是有浏览器兼容性问题, 我们下面将对requestIdleCallback这个方法进行了替换.
从源码里我们知道,react把任务分两种:一个是taskQueue(这个数组是放立即执行的任务), 一个是timerQueue(这个数组是放执行延时任务的)
接下来那么我们看看任务是具有什么样的属性?
var newTask = {
id: taskIdCounter++, // 进入数组时的id
callback, // 执行的任务
priorityLevel, // 任务优先级
startTime, // 开始的时间点 currentTime + delay(option里传入的)
expirationTime, // 过期的时间点 expirationTime = startTime + timeout;
sortIndex: expirationTime, // 排序索引
};
我们通过scheduleCallback传入callback开启任务调度, 声明一个newTask, 根据任务的优先级确定出timeout的值,如果startTime大于currentTime则放入timerQueue,否则放入taskQueue
首先执行的是taskQueue里面的任务, 我们取出第一个需要执行的任务,得到任务的callback并执行它. 任务有可能一次性执行完毕,有可能没有.
taskQueue里的任务都执行完了之后, 执行timerQueue里的任务
// 比较任务的先后顺序的方法
function compare(a, b) {
// Compare sort index first, then task id.
const diff = a.sortIndex - b.sortIndex;
return diff !== 0 ? diff : a.id - b.id;
}
任务执行的顺序是按照sortIndex的大小来比较的,sortIndex越小,执行越靠前, 如果sortIndex大小一样,则比较id,先执行id小的.
那么我们现在回答第三个问题:怎么给任务排序呢?
考虑到任务队列是动态数组. 任务需要执行就push进来, 任务执行完毕后需要pop出去. 如果我们每次数组变更就做一次排序找到最小id或sortIndex那个任务,就很浪费资源. react源码里使用了最小堆解决了任务排序问题.堆顶就是通过比较sortIndex或id的最小任务.
当然有的任务在执行过程中没有全部执行完,后续某一个时刻又开始继续执行. 有的任务是一次性就执行完了,执行完的任务就退出了任务队列.
我在这个项目里github.com/coolara/min… 分支3.0实现了一个简单的任务调度.
下一篇 我们聊聊mini-react的hooks的应用.揭开hooks的面纱!!
大家都知道hooks在函数组件里广泛运用,不能放条件语句里,必须放在函数最外层.
好啦!尽情期待!!