“This is the 21st day of my participation in the Gwen Challenge in November. See details: The Last Gwen Challenge in 2021”

React has functions such as cancelCallback, scheduleCallback, scheduleSyncCallback, and scheduleMicrotask. CancelCallback and scheduleCallback come from a library called Scheduler.

 // packages/react-reconciler/src/Scheduler.js
 import * as Scheduler from 'scheduler';
 ​
 export const scheduleCallback = Scheduler.unstable_scheduleCallback;
 export const cancelCallback = Scheduler.unstable_cancelCallback;
Copy the code

The scheduler is introduced

React, in short, uses it for collaborative scheduling in the browser environment. At first I thought it was a third party library, but it was found in the Packages/Scheduler directory of the React repository.

/ SRC /forks/Scheduler’; The steed goes to scheduler.js, about 600 lines of code, but instead of starting at the beginning, I’ll look at unstable_scheduleCallback and unstable_cancelCallback

unstable_scheduleCallback

Function signatures

 function unstable_scheduleCallback(priorityLevel, callback, options) {}
Copy the code

Code logic

  1. Get the current timecurrentTime, plus the delay timeoptions.delay, calculate the start timestartTime
  2. According to thepriorityLevelYou get different values of thetatimeout
  3. ExpirationTime expirationTime = startTime + timeout
  4. Create a new task
   var newTask = {
     id: taskIdCounter++,
     callback,
     priorityLevel,
     startTime,
     expirationTime,
     sortIndex: -1,
   };
Copy the code
  1. ifnewTaskIs a delayed task, that is, the delay time is not 0, sostartTimeFor sortIndex, put a name namedtimerQueueIs in the priority queue.
  2. iftaskQueueThe task is emptytimerQueueCheck the highest priority in theisHostTimeoutScheduledFlag iftrueThe callcancelHostTimeoutFunction, otherwise markedisHostTimeoutScheduledTo true. Check outisHostTimeoutScheduledAfter that, schedule a timeout. (Essentially, if the new task has the highest priority, the original task is cancelled and the new task is given priority)
 requestHostTimeout(handleTimeout, startTime - currentTime);
Copy the code
  1. ifnewTaskIf the task is not delayed, it is put into the task queue by sorting the index by expiration timetaskQueue.
  2. ifisHostCallbackScheduledTo false andisPerformingWorkFalse, flagisHostCallbackScheduledIf true, executerequestHostCallback(flushWork);
  3. Finally newTask is returned

What does requestHostTimeout and cancelHostTimeout do? What does the requestHostCallback do?

RequestHostTimeout is essentially a setTimeout timer macro task scheduling.

 function requestHostTimeout(callback, ms) {
   taskTimeoutID = localSetTimeout(() => {
     callback(getCurrentTime());
   }, ms);
 }
Copy the code

In this case, localSetTimeout is the alias of the setTimeout function. The alias is used to prevent the user from overwriting the global setTimeout function.

Similarly, localClearTimeout is an alias for clearTimeout. CancelHostTimeout calls localClearTimeout and resets taskTimeoutID to -1.

As for requestHostCallback, it takes a callback argument assigned to the global variable scheduledHostCallback, Then open callbackschedulePerformWorkUntilDeadline – > performWorkUntilDeadline – > scheduledHostCallback – > schedulePerformWorkUntilDeadline news circulation until scheduledHostCallback call return values to false, will scheduledHostCallback reset to null.

FlushWork {flushWork} flushWork {requestHostCallback} flushWork {flushWork}

function flushWork(hasTimeRemaining, initialTime) { isHostCallbackScheduled = false; If (isHostTimeoutScheduled) {timeout isHostTimeoutScheduled = false; if (isHostTimeoutScheduled) {timeout isHostTimeoutScheduled = false; cancelHostTimeout(); } isPerformingWork = true; const previousPriorityLevel = currentPriorityLevel; try { return workLoop(hasTimeRemaining, initialTime); } finally { currentTask = null; currentPriorityLevel = previousPriorityLevel; isPerformingWork = false; }}Copy the code

unstable_cancelCallback

The simple thing is to empty the callback field of the input parameter

 function unstable_cancelCallback(task) {
   if (enableProfiling) {
     // ...
   }
 
   // Null out the callback to indicate the task has been canceled. (Can't
   // remove from the queue because you can't remove arbitrary nodes from an
   // array based heap, only the first one.)
   task.callback = null;
 }
Copy the code

Next up

  1. What does workLoop in flushWork do?
  2. What is the overall principle of task scheduling in this library?