- Published on
Understanding React Delayed Task Scheduling
Understanding React Delayed Task Scheduling
unstable_scheduleCallback
function unstable_scheduleCallback(priorityLevel, callback, options) {
//...
if (startTime > currentTime) {
// 调度一个延时任务
requestHostTimeout(handleTimeout, startTime - currentTime)
} else {
// 调度一个普通任务
requestHostCallback(flushWork)
}
}
- 可以看到,调度一个延时任务的时候,主要是执行
requestHostTimeout
requestHostTimeout
// 实际上在浏览器环境就是 setTimeout
const localSetTimeout = typeof setTimeout === 'function' ? setTimeout : null
/**
*
* @param {*} callback 就是传入的 handleTimeout
* @param {*} ms 延时的时间
*/
function requestHostTimeout(callback, ms) {
taskTimeoutID = localSetTimeout(() => {
callback(getCurrentTime())
}, ms)
/**
* 因此,上面的代码,就可以看作是
* id = setTimeout(function(){
* handleTimeout(getCurrentTime())
* }, ms)
*/
}
可以看到,requestHostTimeout
实际上就是调用 setTimeout
,然后在 setTimeout
中,调用传入的 handleTimeout
handleTimeout
/**
*
* @param {*} currentTime 当前时间
*/
function handleTimeout(currentTime) {
isHostTimeoutScheduled = false
// 遍历timerQueue,将时间已经到了的延时任务放入到 taskQueue
advanceTimers(currentTime)
if (!isHostCallbackScheduled) {
if (peek(taskQueue) !== null) {
// 从普通任务队列中拿一个任务出来
isHostCallbackScheduled = true
// 采用调度普通任务的方式进行调度
requestHostCallback(flushWork)
} else {
// taskQueue任务队列里面是空的
// 再从 timerQueue 队列取一个任务出来
// peek 是小顶堆中提供的方法
const firstTimer = peek(timerQueue)
if (firstTimer !== null) {
// 取出来了,接下来取出的延时任务仍然使用 requestHostTimeout 进行调度
requestHostTimeout(handleTimeout, firstTimer.startTime - currentTime)
}
}
}
}
handleTimeout
里面主要就是调用advanceTimers
方法,该方法的作用是将时间已经到了的延时任务放入到taskQueue
,那么现在taskQueue
里面就有要执行的任务,然后使用requestHostCallback
进行调度。如果taskQueue
里面没有任务了,再次从timerQueue
里面去获取延时任务,然后通过requestHostTimeout
进行调度。
Flow Diagram
Scheduler
大致的流程图如下: