import { unstable_scheduleCallback as scheduleCallback } from "./forks/Scheduler.js";
function normalTask(id) {
return () => {
console.log('task:', id)
}
}
scheduleCallback(0, normalTask(1)); // 5000
scheduleCallback(1, normalTask(2)); // -1
scheduleCallback(2, normalTask(3)); // 250
scheduleCallback(3, normalTask(4)); // 5000
scheduleCallback(4, normalTask(5)); // 10000
scheduleCallback(5, normalTask(6)); // Never times out
scheduleCallback第一个参数是优先级,expirationTime = startTime + 注释后的数字
注释后的数字是必须执行时间,即使这帧超时了也要执行
taskQueue按照过期时间排序然后执行,执行完后更新当前时间,所以taskQueue的顺序是1,2,0,3,4,5
在执行taskQueue的过程中,当任务优先级不是1时,就有可能被截断,Scheduler按照5ms为切割点,从任务开始执行到执行完a任务后,时间超过5ms,如果a+1没有超时,这个任务队列在这轮宏任务中就先不执行了,将主线程给其他任务使用
之后在下一次循环中,从a+1这个任务开始继续执行
上图可以看出,轮到task3时间已经不够了,因此task3在下一次宏任务中执行
如果有个很长很长的任务
function longTask(id) { // 预计花费800+ms
return () => {
console.log('task:', id)
let startTime = +new Date()
for(let i = 0; i < 1000000000; i++) {
;
}
let lastTime = +new Date() - startTime
console.log("longTask spend:", lastTime)
}
}
scheduleCallback(2, longTask(7));
如上图所示,整个taskQueue被截成3段,2 | 3,7 | 1,4,5,6
当task3执行完后,时间还很充裕,就执行task7这个长任务,等它执行完后,这帧花费的时间已经800多ms了,之后执行task1,由于task1超时时间是5000+ms,没有超时,就从这里截断。
如果有个延迟任务
scheduleCallback(2, normalTask(8), {
delay: 500
});
task8的过期时间是500+250 = 750
那么此时task7执行完后,由于task8超时了,所以在执行完task8后再截断
如果task返回是一个函数
const result = 3;
let currentResult = 0;
function calculate() {
console.log('calculate:', currentResult);
currentResult++;
if (currentResult < result) {
return calculate;
}
return null;
}
calculate()会调用自己三次
此时Scheduler会判断当callback是函数的时候,这个此时循环会直接停止,并把返回的callback赋值给当前task,等待下一次宏任务继续从这个task开始执行