react源码学习之Scheduler
简介
Scheduler主要用于调度执行Reconciler
组成
api
- unstable_scheduleCallback
- unstable_cancelCallback
调度回调有两种方式
- setTimeout
- 通过MessageChannel
Task
为任务调度单元
type Task={id:number,callback:Callback|null,priorityLevel:PriorityLevel,startTime:number,expirationTime:number,sortIndex:number,isQueued?:boolean,};双堆
维护两个最小堆,按Task的sortIndex排序
taskQueue:排序键为expirationTime,startTime小于等于当前时间currentTime的任务放入此堆中timerQueue:排序键为startTime,startTime大于当前时间currentTime的任务放入此堆中
vartaskQueue:Array<Task>=[];vartimerQueue:Array<Task>=[];优先级 到超时时间 的映射
| 优先级 | timeout超时时间 |
|---|---|
ImmediatePriority | -1立即超时 |
UserBlockingPriority | const userBlockingPriorityTimeout = 250 |
IdlePriority | maxSigned31BitInt = 1073741823永远不会超时 |
LowPriority | const lowPriorityTimeout = 10000 |
NormalPriority | const normalPriorityTimeout = 5000 |
调度工作循环workLoop
functionworkLoop(initialTime:number){letcurrentTime=initialTime;advanceTimers(currentTime);currentTask=peek(taskQueue);while(currentTask!==null){if(!enableAlwaysYieldScheduler){if(currentTask.expirationTime>currentTime&&shouldYieldToHost()){// This currentTask hasn't expired, and we've reached the deadline.break;}}// $FlowFixMe[incompatible-use] found when upgrading Flowconstcallback=currentTask.callback;if(typeofcallback==='function'){// $FlowFixMe[incompatible-use] found when upgrading FlowcurrentTask.callback=null;// $FlowFixMe[incompatible-use] found when upgrading FlowcurrentPriorityLevel=currentTask.priorityLevel;// $FlowFixMe[incompatible-use] found when upgrading FlowconstdidUserCallbackTimeout=currentTask.expirationTime<=currentTime;if(enableProfiling){// $FlowFixMe[incompatible-call] found when upgrading FlowmarkTaskRun(currentTask,currentTime);}constcontinuationCallback=callback(didUserCallbackTimeout);currentTime=getCurrentTime();if(typeofcontinuationCallback==='function'){// If a continuation is returned, immediately yield to the main thread// regardless of how much time is left in the current time slice.// $FlowFixMe[incompatible-use] found when upgrading FlowcurrentTask.callback=continuationCallback;if(enableProfiling){// $FlowFixMe[incompatible-call] found when upgrading FlowmarkTaskYield(currentTask,currentTime);}advanceTimers(currentTime);returntrue;}else{if(enableProfiling){// $FlowFixMe[incompatible-call] found when upgrading FlowmarkTaskCompleted(currentTask,currentTime);// $FlowFixMe[incompatible-use] found when upgrading FlowcurrentTask.isQueued=false;}if(currentTask===peek(taskQueue)){pop(taskQueue);}advanceTimers(currentTime);}}else{pop(taskQueue);}currentTask=peek(taskQueue);if(enableAlwaysYieldScheduler){if(currentTask===null||currentTask.expirationTime>currentTime){// This currentTask hasn't expired we yield to the browser task.break;}}}// Return whether there's additional workif(currentTask!==null){returntrue;}else{constfirstTimer=peek(timerQueue);if(firstTimer!==null){requestHostTimeout(handleTimeout,firstTimer.startTime-currentTime);}returnfalse;}}AI数字营销平台
