React是如何利用堆进行任务调度的?

1,568 阅读2分钟

最近一直在做 LeetCode 题解的相关输出,
有的小伙伴可能会有疑惑,学了算法后,在前端中有哪些地方用到了算法呢?
今天我们就来聊一聊 React 中是如何利用堆维护任务队列的。

业务场景

React 中有很多任务,
例如 用户点击、用户输入以及 setState 等等,而这些任务又有优先级的区分。
比如用户的点击和输入,肯定是高优先级任务,要优先响应,
load 以及 animation 事件的优先级肯定要低一些。

如果队列中有了一些低优先级任务,此时新进来的高优先级任务就要插队执行,那么 React 是如何管理这些任务的呢?

源码地址

React 源码中有目录 packages/scheduler,该目录就是 React 任务调度模块相关。
该目录 src
Scheduler.js 实现了任务调度相关逻辑
SchedulerMinHeap.js 实现了堆

小顶堆任务调度

React 会有一系列规则定义每个任务的优先级,最后的表现就是 React 会将每个任务包装为一个任务对象 newTask 319行,该对象会存在两个属性 idsortIndex
其中 sortIndex 标识当前任务的优先级, id 标识每个任务的先后顺序。

React 中存放任务的数组 taskQueue 会被模拟为一个小顶堆,
该小顶堆的 compare 逻辑是优先比较 sortIndex(即任务的优先级),
如果 sortIndex 相同,则比较 id(即任务创建的先后顺序)。

因为堆的性质是维护一个最值在堆顶,所以每次堆顶任务(对应任务数组中的第一个元素)就是当前任务队列中优先级最高的任务,这样只需要每次获取堆顶任务执行即可。

堆顶任务取出之后,只需要对小顶堆进行弹堆操作后自上向下的平衡调整,则堆顶又维护了当前任务队列中优先级最高的任务。

这样通过堆维护任务队列,每次获取优先级最高的任务的时间复杂度是 O(1) 的,插入和弹出操作后的平衡调整时间复杂度是 O(logn)的,整体是非常高效的。

end

以上就是堆在 React 任务调度中的应用,你学会了吗?