每日一报
setTimeout | MessageChannel
Material Related
- 执行顺序测试
node v22.14.0
- 当
setTimeout的延迟值delay <= 4ms时,其执行时机比MessageChannel快。 - 当延迟值
delay == 5ms时,两者执行时机差不多,顺序不确定。 - 当延迟值
delay > 5ms时,MessageChannel更快。
chrome 137
- 当
setTimeout的延迟值delay == 0ms时,表现与MessageChannel一致。 - 当延迟值
delay > 0ms时,setTimeout表现比MessageChannel慢。
safari 18.5
- 当
setTimeout的延迟值delay <= 2ms时,表现与MessageChannel一致。 - 当延迟值
delay > 2ms时,setTimeout表现比MessageChannel慢。
非激活态下的 setTimeout
chrome 137 中额外测试发现,setTimeout(delay = 1000) 在页面处于非激活态 5min 后会发现 delay 时间变成了 1min,与此同时期间的延迟时间存在突变现象。
| Delay Time(ms) | Non-active Tab Time(ms) |
|---|---|
| 2016 | 147176 |
| 1997 | 244153 |
| 2047 | 253205 |
| 1001 | 276157 |
| 1998 | 278155 |
| ... | ... |
| 1005 | 300161 |
| 13059 | 313320(突变) |
| 60019 | 373341(稳定突变) |
| 60049 | 433478 |
| 59998 | 493490 |
(() => {
let time = new Date().getTime();
const startTime = new Date().getTime();
const trigger = () => {
setTimeout(() => {
console.log('Delay Time(ms): ', new Date().getTime() - time);
console.log(
'Non-active Tab Time(ms): ',
new Date().getTime() - startTime
);
time = new Date().getTime();
trigger();
}, 1000);
};
trigger();
})();setTimeout 与 requestIdleCallback
const delayTime = 1;
const callback = () => {
const timer = setTimeout(() => {
console.log('setTimeout');
clearTimeout(timer);
}, delayTime);
requestIdleCallback(() => {
console.log('requestIdleCallback');
});
};
setInterval(() => {
callback();
}, 3000);在 chrome 137 中,setTimeout 的延迟值 delay <= 1ms 时,setTimeout 执行时机会比 requestIdleCallback 快。
在 firefox 139 中,setTimeout 的延迟值 delay <= 3ms 时,setTimeout 执行时机会比 requestIdleCallback 快。
react scheduler 默认会将 MessageChannel 作为任务调度器,而将 setTimeout 作为备用任务调度器。原因在与 MessageChannel 会积极推送宏任务,而 setTimeout 在部分场景中(非激活态和嵌套 setTimeout 的 4ms 机制时)采用延迟推送宏任务。
setTimeout | setInterval | requestAnimationFrame | requestIdleCallback
Baseline
测试环境: chrome 137.0.7151.57 (Official Build) (arm64)
测试用例:
const startTime = new Date().getTime();
let exCount = 0;
const callback = () => {
console.log(
`VI-LOG_Count: ${++exCount}, Current Time: ${new Date().getTime() - startTime}`
);
const callback = (function (exCount) {
const count = exCount;
return function (info) {
console.log(
`VI-LOG_${info}_${count} -- Current Time`,
new Date().getTime() - startTime
);
};
})(exCount);
requestIdleCallback(callback.bind(null, 'requestIdleCallback'));
requestAnimationFrame(callback.bind(null, 'requestAnimationFrame'));
};
setInterval(() => {
callback();
}, 1000);let timer = null;
let start = new Date().getTime();
let count = 0;
const run = () => {
timer = setTimeout(() => {
const currentTime = new Date().getTime();
console.log(`VP_LOG_${++count} - ${currentTime - start}`);
start = currentTime;
clearTimeout(timer);
run();
}, 1000);
};
run();Test1 的日志输出
VI-LOG_Count: 1, Current Time: 1034
VI-LOG_requestAnimationFrame_1 -- Current Time 1042
VI-LOG_requestIdleCallback_1 -- Current Time 1043
VI-LOG_Count: 2, Current Time: 2001
VI-LOG_requestAnimationFrame_2 -- Current Time 2001
VI-LOG_requestIdleCallback_2 -- Current Time 2001
VI-LOG_Count: 3, Current Time: 3001
VI-LOG_requestAnimationFrame_3 -- Current Time 3001
VI-LOG_requestIdleCallback_3 -- Current Time 3002
VI-LOG_Count: 4, Current Time: 4000
VI-LOG_requestAnimationFrame_4 -- Current Time 4001
VI-LOG_requestIdleCallback_4 -- Current Time 4001
VI-LOG_Count: 5, Current Time: 5001
VI-LOG_requestAnimationFrame_5 -- Current Time 5002
VI-LOG_requestIdleCallback_5 -- Current Time 5002
VI-LOG_Count: 6, Current Time: 6001
VI-LOG_requestAnimationFrame_6 -- Current Time 6001
VI-LOG_requestIdleCallback_6 -- Current Time 6001
VI-LOG_Count: 7, Current Time: 7002
VI-LOG_requestAnimationFrame_7 -- Current Time 7002
VI-LOG_requestIdleCallback_7 -- Current Time 7004
VI-LOG_Count: 8, Current Time: 8001
VI-LOG_requestAnimationFrame_8 -- Current Time 8002
VI-LOG_requestIdleCallback_8 -- Current Time 8002
VI-LOG_Count: 9, Current Time: 9002
VI-LOG_requestAnimationFrame_9 -- Current Time 9008
VI-LOG_requestIdleCallback_9 -- Current Time 9073
VI-LOG_Count: 10, Current Time: 10002
VI-LOG_requestIdleCallback_10 -- Current Time 10002
VI-LOG_requestAnimationFrame_10 -- Current Time 10003
VI-LOG_Count: 11, Current Time: 11002
VI-LOG_requestAnimationFrame_11 -- Current Time 11003
VI-LOG_requestIdleCallback_11 -- Current Time 11003
VI-LOG_Count: 12, Current Time: 12001
VI-LOG_requestAnimationFrame_12 -- Current Time 12002
VI-LOG_requestIdleCallback_12 -- Current Time 12002
VI-LOG_Count: 13, Current Time: 13002
VI-LOG_requestAnimationFrame_13 -- Current Time 13006
VI-LOG_requestIdleCallback_13 -- Current Time 13006
VI-LOG_Count: 14, Current Time: 14001
VI-LOG_requestAnimationFrame_14 -- Current Time 14003
VI-LOG_requestIdleCallback_14 -- Current Time 14005
VI-LOG_Count: 15, Current Time: 15002
VI-LOG_requestAnimationFrame_15 -- Current Time 15003
VI-LOG_requestIdleCallback_15 -- Current Time 15004
VI-LOG_Count: 16, Current Time: 16397
VI-LOG_requestIdleCallback_16 -- Current Time 16399
VI-LOG_Count: 17, Current Time: 17381
VI-LOG_requestIdleCallback_17 -- Current Time 17382
VI-LOG_Count: 18, Current Time: 18380
VI-LOG_requestIdleCallback_18 -- Current Time 18381
VI-LOG_Count: 19, Current Time: 19376
VI-LOG_requestIdleCallback_19 -- Current Time 19376
VI-LOG_Count: 20, Current Time: 20378
VI-LOG_requestIdleCallback_20 -- Current Time 20379
VI-LOG_Count: 21, Current Time: 21376
VI-LOG_requestIdleCallback_21 -- Current Time 21376
VI-LOG_Count: 22, Current Time: 22379
VI-LOG_requestIdleCallback_22 -- Current Time 22387
VI-LOG_Count: 23, Current Time: 23376
VI-LOG_requestIdleCallback_23 -- Current Time 23377
VI-LOG_Count: 24, Current Time: 24376
VI-LOG_requestIdleCallback_24 -- Current Time 24377
VI-LOG_Count: 25, Current Time: 25376
VI-LOG_Count: 26, Current Time: 26377
VI-LOG_Count: 27, Current Time: 27377
VI-LOG_Count: 28, Current Time: 28377
VI-LOG_Count: 29, Current Time: 29378
VI-LOG_Count: 30, Current Time: 30376
VI-LOG_Count: 31, Current Time: 31377
VI-LOG_Count: 32, Current Time: 32377
VI-LOG_Count: 33, Current Time: 33378
VI-LOG_Count: 34, Current Time: 34378
VI-LOG_Count: 35, Current Time: 35376
VI-LOG_Count: 36, Current Time: 36379
VI-LOG_Count: 37, Current Time: 37380
VI-LOG_Count: 38, Current Time: 38380
VI-LOG_Count: 39, Current Time: 39377
VI-LOG_Count: 40, Current Time: 40377
VI-LOG_Count: 41, Current Time: 41378
VI-LOG_Count: 42, Current Time: 42377
VI-LOG_Count: 43, Current Time: 43378
VI-LOG_Count: 44, Current Time: 44377
VI-LOG_Count: 45, Current Time: 45377
VI-LOG_Count: 46, Current Time: 46381
VI-LOG_Count: 47, Current Time: 47378
VI-LOG_Count: 48, Current Time: 48378
VI-LOG_Count: 49, Current Time: 49378
VI-LOG_Count: 50, Current Time: 50377
VI-LOG_Count: 51, Current Time: 51377
VI-LOG_Count: 52, Current Time: 52377
VI-LOG_Count: 53, Current Time: 53378
VI-LOG_Count: 54, Current Time: 54377
VI-LOG_Count: 55, Current Time: 55378
VI-LOG_Count: 56, Current Time: 56377
VI-LOG_Count: 57, Current Time: 57377
VI-LOG_Count: 58, Current Time: 58377
VI-LOG_Count: 59, Current Time: 59377
VI-LOG_Count: 60, Current Time: 60383
VI-LOG_Count: 61, Current Time: 61379
VI-LOG_Count: 62, Current Time: 62376
VI-LOG_Count: 63, Current Time: 63378
VI-LOG_Count: 64, Current Time: 64378
VI-LOG_Count: 65, Current Time: 65379
VI-LOG_Count: 66, Current Time: 66379
VI-LOG_Count: 67, Current Time: 67379
VI-LOG_Count: 68, Current Time: 68377
VI-LOG_Count: 69, Current Time: 69388
VI-LOG_Count: 70, Current Time: 70421
VI-LOG_Count: 71, Current Time: 71380
VI-LOG_Count: 72, Current Time: 72381
VI-LOG_Count: 73, Current Time: 73389
VI-LOG_Count: 74, Current Time: 74378
VI-LOG_Count: 75, Current Time: 75394
VI-LOG_Count: 76, Current Time: 76390
VI-LOG_Count: 77, Current Time: 77400
VI-LOG_Count: 78, Current Time: 78380
VI-LOG_Count: 79, Current Time: 79378
VI-LOG_Count: 80, Current Time: 80378
VI-LOG_Count: 81, Current Time: 81393
VI-LOG_Count: 82, Current Time: 82381
VI-LOG_Count: 83, Current Time: 83402
VI-LOG_Count: 84, Current Time: 84402
VI-LOG_Count: 85, Current Time: 85381
VI-LOG_Count: 86, Current Time: 86386
VI-LOG_Count: 87, Current Time: 87382
VI-LOG_Count: 88, Current Time: 88399
VI-LOG_Count: 89, Current Time: 89383
VI-LOG_Count: 90, Current Time: 90384
VI-LOG_Count: 91, Current Time: 91381
VI-LOG_Count: 92, Current Time: 92423
VI-LOG_Count: 93, Current Time: 93383
VI-LOG_Count: 94, Current Time: 94379
VI-LOG_Count: 95, Current Time: 95391
VI-LOG_Count: 96, Current Time: 96391
VI-LOG_Count: 97, Current Time: 97381
VI-LOG_Count: 98, Current Time: 98492
VI-LOG_Count: 99, Current Time: 99381
VI-LOG_Count: 100, Current Time: 100385
VI-LOG_Count: 101, Current Time: 101381
VI-LOG_Count: 102, Current Time: 102379
VI-LOG_Count: 103, Current Time: 103378
VI-LOG_Count: 104, Current Time: 104379
VI-LOG_Count: 105, Current Time: 105377
VI-LOG_Count: 106, Current Time: 106381
VI-LOG_Count: 107, Current Time: 107379
VI-LOG_Count: 108, Current Time: 108380
VI-LOG_Count: 109, Current Time: 109380
VI-LOG_Count: 110, Current Time: 110385
VI-LOG_Count: 111, Current Time: 111379
VI-LOG_Count: 112, Current Time: 112392
VI-LOG_Count: 113, Current Time: 113381
VI-LOG_Count: 114, Current Time: 114380
VI-LOG_Count: 115, Current Time: 115391
VI-LOG_Count: 116, Current Time: 116381
VI-LOG_Count: 117, Current Time: 117394
VI-LOG_Count: 118, Current Time: 118382
VI-LOG_Count: 119, Current Time: 119379
VI-LOG_Count: 120, Current Time: 120380
VI-LOG_Count: 121, Current Time: 121382
VI-LOG_Count: 122, Current Time: 122380
VI-LOG_Count: 123, Current Time: 123379
VI-LOG_Count: 124, Current Time: 124379
VI-LOG_Count: 125, Current Time: 125379
VI-LOG_Count: 126, Current Time: 126379
VI-LOG_Count: 127, Current Time: 127393
VI-LOG_Count: 128, Current Time: 128391
VI-LOG_Count: 129, Current Time: 129379
VI-LOG_Count: 130, Current Time: 130379
VI-LOG_Count: 131, Current Time: 131379
VI-LOG_Count: 132, Current Time: 132393
VI-LOG_Count: 133, Current Time: 133397
VI-LOG_Count: 134, Current Time: 134380
VI-LOG_Count: 135, Current Time: 135379
VI-LOG_Count: 136, Current Time: 136383
VI-LOG_Count: 137, Current Time: 137383
VI-LOG_Count: 138, Current Time: 138379
VI-LOG_Count: 139, Current Time: 139381
VI-LOG_Count: 140, Current Time: 140381
VI-LOG_Count: 141, Current Time: 141380
VI-LOG_Count: 142, Current Time: 142380
VI-LOG_Count: 143, Current Time: 143382
VI-LOG_Count: 144, Current Time: 144443
VI-LOG_Count: 145, Current Time: 145381
VI-LOG_requestAnimationFrame_16 -- Current Time 145814
VI-LOG_requestAnimationFrame_17 -- Current Time 145814
VI-LOG_requestAnimationFrame_18 -- Current Time 145814
VI-LOG_requestAnimationFrame_19 -- Current Time 145814
VI-LOG_requestAnimationFrame_20 -- Current Time 145815
VI-LOG_requestAnimationFrame_21 -- Current Time 145815
VI-LOG_requestAnimationFrame_22 -- Current Time 145815
VI-LOG_requestAnimationFrame_23 -- Current Time 145815
VI-LOG_requestAnimationFrame_24 -- Current Time 145815
VI-LOG_requestAnimationFrame_25 -- Current Time 145815
VI-LOG_requestAnimationFrame_26 -- Current Time 145815
VI-LOG_requestAnimationFrame_27 -- Current Time 145815
VI-LOG_requestAnimationFrame_28 -- Current Time 145815
VI-LOG_requestAnimationFrame_29 -- Current Time 145815
VI-LOG_requestAnimationFrame_30 -- Current Time 145815
VI-LOG_requestAnimationFrame_31 -- Current Time 145815
VI-LOG_requestAnimationFrame_32 -- Current Time 145815
VI-LOG_requestAnimationFrame_33 -- Current Time 145815
VI-LOG_requestAnimationFrame_34 -- Current Time 145815
VI-LOG_requestAnimationFrame_35 -- Current Time 145815
VI-LOG_requestAnimationFrame_36 -- Current Time 145815
VI-LOG_requestAnimationFrame_37 -- Current Time 145815
VI-LOG_requestAnimationFrame_38 -- Current Time 145815
VI-LOG_requestAnimationFrame_39 -- Current Time 145815
VI-LOG_requestAnimationFrame_40 -- Current Time 145816
VI-LOG_requestAnimationFrame_41 -- Current Time 145816
VI-LOG_requestAnimationFrame_42 -- Current Time 145816
VI-LOG_requestAnimationFrame_43 -- Current Time 145816
VI-LOG_requestAnimationFrame_44 -- Current Time 145816
VI-LOG_requestAnimationFrame_45 -- Current Time 145816
VI-LOG_requestAnimationFrame_46 -- Current Time 145816
VI-LOG_requestAnimationFrame_47 -- Current Time 145816
VI-LOG_requestAnimationFrame_48 -- Current Time 145816
VI-LOG_requestAnimationFrame_49 -- Current Time 145816
VI-LOG_requestAnimationFrame_50 -- Current Time 145816
VI-LOG_requestAnimationFrame_51 -- Current Time 145816
VI-LOG_requestAnimationFrame_52 -- Current Time 145816
VI-LOG_requestAnimationFrame_53 -- Current Time 145817
VI-LOG_requestAnimationFrame_54 -- Current Time 145817
VI-LOG_requestAnimationFrame_55 -- Current Time 145817
VI-LOG_requestAnimationFrame_56 -- Current Time 145817
VI-LOG_requestAnimationFrame_57 -- Current Time 145817
VI-LOG_requestAnimationFrame_58 -- Current Time 145817
VI-LOG_requestAnimationFrame_59 -- Current Time 145817
VI-LOG_requestAnimationFrame_60 -- Current Time 145817
VI-LOG_requestAnimationFrame_61 -- Current Time 145817
VI-LOG_requestAnimationFrame_62 -- Current Time 145817
VI-LOG_requestAnimationFrame_63 -- Current Time 145817
VI-LOG_requestAnimationFrame_64 -- Current Time 145817
VI-LOG_requestAnimationFrame_65 -- Current Time 145817
VI-LOG_requestAnimationFrame_66 -- Current Time 145817
VI-LOG_requestAnimationFrame_67 -- Current Time 145817
VI-LOG_requestAnimationFrame_68 -- Current Time 145817
VI-LOG_requestAnimationFrame_69 -- Current Time 145817
VI-LOG_requestAnimationFrame_70 -- Current Time 145817
VI-LOG_requestAnimationFrame_71 -- Current Time 145817
VI-LOG_requestAnimationFrame_72 -- Current Time 145818
VI-LOG_requestAnimationFrame_73 -- Current Time 145818
VI-LOG_requestAnimationFrame_74 -- Current Time 145818
VI-LOG_requestAnimationFrame_75 -- Current Time 145818
VI-LOG_requestAnimationFrame_76 -- Current Time 145818
VI-LOG_requestAnimationFrame_77 -- Current Time 145818
VI-LOG_requestAnimationFrame_78 -- Current Time 145818
VI-LOG_requestAnimationFrame_79 -- Current Time 145818
VI-LOG_requestAnimationFrame_80 -- Current Time 145818
VI-LOG_requestAnimationFrame_81 -- Current Time 145818
VI-LOG_requestAnimationFrame_82 -- Current Time 145818
VI-LOG_requestAnimationFrame_83 -- Current Time 145818
VI-LOG_requestAnimationFrame_84 -- Current Time 145818
VI-LOG_requestAnimationFrame_85 -- Current Time 145818
VI-LOG_requestAnimationFrame_86 -- Current Time 145818
VI-LOG_requestAnimationFrame_87 -- Current Time 145818
VI-LOG_requestAnimationFrame_88 -- Current Time 145818
VI-LOG_requestAnimationFrame_89 -- Current Time 145818
VI-LOG_requestAnimationFrame_90 -- Current Time 145818
VI-LOG_requestAnimationFrame_91 -- Current Time 145818
VI-LOG_requestAnimationFrame_92 -- Current Time 145819
VI-LOG_requestAnimationFrame_93 -- Current Time 145819
VI-LOG_requestAnimationFrame_94 -- Current Time 145819
VI-LOG_requestAnimationFrame_95 -- Current Time 145819
VI-LOG_requestAnimationFrame_96 -- Current Time 145819
VI-LOG_requestAnimationFrame_97 -- Current Time 145819
VI-LOG_requestAnimationFrame_98 -- Current Time 145819
VI-LOG_requestAnimationFrame_99 -- Current Time 145819
VI-LOG_requestAnimationFrame_100 -- Current Time 145819
VI-LOG_requestAnimationFrame_101 -- Current Time 145819
VI-LOG_requestAnimationFrame_102 -- Current Time 145819
VI-LOG_requestAnimationFrame_103 -- Current Time 145819
VI-LOG_requestAnimationFrame_104 -- Current Time 145819
VI-LOG_requestAnimationFrame_105 -- Current Time 145819
VI-LOG_requestAnimationFrame_106 -- Current Time 145819
VI-LOG_requestAnimationFrame_107 -- Current Time 145819
VI-LOG_requestAnimationFrame_108 -- Current Time 145819
VI-LOG_requestAnimationFrame_109 -- Current Time 145819
VI-LOG_requestAnimationFrame_110 -- Current Time 145819
VI-LOG_requestAnimationFrame_111 -- Current Time 145819
VI-LOG_requestAnimationFrame_112 -- Current Time 145820
VI-LOG_requestAnimationFrame_113 -- Current Time 145820
VI-LOG_requestAnimationFrame_114 -- Current Time 145820
VI-LOG_requestAnimationFrame_115 -- Current Time 145820
VI-LOG_requestAnimationFrame_116 -- Current Time 145820
VI-LOG_requestAnimationFrame_117 -- Current Time 145820
VI-LOG_requestAnimationFrame_118 -- Current Time 145820
VI-LOG_requestAnimationFrame_119 -- Current Time 145820
VI-LOG_requestAnimationFrame_120 -- Current Time 145820
VI-LOG_requestAnimationFrame_121 -- Current Time 145820
VI-LOG_requestAnimationFrame_122 -- Current Time 145820
VI-LOG_requestAnimationFrame_123 -- Current Time 145820
VI-LOG_requestAnimationFrame_124 -- Current Time 145820
VI-LOG_requestAnimationFrame_125 -- Current Time 145820
VI-LOG_requestAnimationFrame_126 -- Current Time 145820
VI-LOG_requestAnimationFrame_127 -- Current Time 145820
VI-LOG_requestAnimationFrame_128 -- Current Time 145820
VI-LOG_requestAnimationFrame_129 -- Current Time 145820
VI-LOG_requestAnimationFrame_130 -- Current Time 145820
VI-LOG_requestAnimationFrame_131 -- Current Time 145820
VI-LOG_requestAnimationFrame_132 -- Current Time 145821
VI-LOG_requestAnimationFrame_133 -- Current Time 145821
VI-LOG_requestAnimationFrame_134 -- Current Time 145821
VI-LOG_requestAnimationFrame_135 -- Current Time 145821
VI-LOG_requestAnimationFrame_136 -- Current Time 145821
VI-LOG_requestAnimationFrame_137 -- Current Time 145821
VI-LOG_requestAnimationFrame_138 -- Current Time 145821
VI-LOG_requestAnimationFrame_139 -- Current Time 145821
VI-LOG_requestAnimationFrame_140 -- Current Time 145821
VI-LOG_requestAnimationFrame_141 -- Current Time 145821
VI-LOG_requestAnimationFrame_142 -- Current Time 145821
VI-LOG_requestAnimationFrame_143 -- Current Time 145821
VI-LOG_requestAnimationFrame_144 -- Current Time 145821
VI-LOG_requestAnimationFrame_145 -- Current Time 145821
VI-LOG_requestIdleCallback_25 -- Current Time 145822
VI-LOG_requestIdleCallback_26 -- Current Time 145822
VI-LOG_requestIdleCallback_27 -- Current Time 145822
VI-LOG_requestIdleCallback_28 -- Current Time 145822
VI-LOG_requestIdleCallback_29 -- Current Time 145822
VI-LOG_requestIdleCallback_30 -- Current Time 145822
VI-LOG_requestIdleCallback_31 -- Current Time 145822
VI-LOG_requestIdleCallback_32 -- Current Time 145822
VI-LOG_requestIdleCallback_33 -- Current Time 145822
VI-LOG_requestIdleCallback_34 -- Current Time 145822
VI-LOG_requestIdleCallback_35 -- Current Time 145822
VI-LOG_requestIdleCallback_36 -- Current Time 145823
VI-LOG_requestIdleCallback_37 -- Current Time 145823
VI-LOG_requestIdleCallback_38 -- Current Time 145823
VI-LOG_requestIdleCallback_39 -- Current Time 145823
VI-LOG_requestIdleCallback_40 -- Current Time 145823
VI-LOG_requestIdleCallback_41 -- Current Time 145823
VI-LOG_requestIdleCallback_42 -- Current Time 145823
VI-LOG_requestIdleCallback_43 -- Current Time 145823
VI-LOG_requestIdleCallback_44 -- Current Time 145823
VI-LOG_requestIdleCallback_45 -- Current Time 145823
VI-LOG_requestIdleCallback_46 -- Current Time 145823
VI-LOG_requestIdleCallback_47 -- Current Time 145823
VI-LOG_requestIdleCallback_48 -- Current Time 145823
VI-LOG_requestIdleCallback_49 -- Current Time 145823
VI-LOG_requestIdleCallback_50 -- Current Time 145824
VI-LOG_requestIdleCallback_51 -- Current Time 145824
VI-LOG_requestIdleCallback_52 -- Current Time 145824
VI-LOG_requestIdleCallback_53 -- Current Time 145824
VI-LOG_requestIdleCallback_54 -- Current Time 145824
VI-LOG_requestIdleCallback_55 -- Current Time 145824
VI-LOG_requestIdleCallback_56 -- Current Time 145824
VI-LOG_requestIdleCallback_57 -- Current Time 145824
VI-LOG_requestIdleCallback_58 -- Current Time 145824
VI-LOG_requestIdleCallback_59 -- Current Time 145824
VI-LOG_requestIdleCallback_60 -- Current Time 145824
VI-LOG_requestIdleCallback_61 -- Current Time 145824
VI-LOG_requestIdleCallback_62 -- Current Time 145824
VI-LOG_requestIdleCallback_63 -- Current Time 145825
VI-LOG_requestIdleCallback_64 -- Current Time 145825
VI-LOG_requestIdleCallback_65 -- Current Time 145825
VI-LOG_requestIdleCallback_66 -- Current Time 145825
VI-LOG_requestIdleCallback_67 -- Current Time 145825
VI-LOG_requestIdleCallback_68 -- Current Time 145825
VI-LOG_requestIdleCallback_69 -- Current Time 145825
VI-LOG_requestIdleCallback_70 -- Current Time 145825
VI-LOG_requestIdleCallback_71 -- Current Time 145825
VI-LOG_requestIdleCallback_72 -- Current Time 145825
VI-LOG_requestIdleCallback_73 -- Current Time 145825
VI-LOG_requestIdleCallback_74 -- Current Time 145825
VI-LOG_requestIdleCallback_75 -- Current Time 145825
VI-LOG_requestIdleCallback_76 -- Current Time 145826
VI-LOG_requestIdleCallback_77 -- Current Time 145826
VI-LOG_requestIdleCallback_78 -- Current Time 145826
VI-LOG_requestIdleCallback_79 -- Current Time 145826
VI-LOG_requestIdleCallback_80 -- Current Time 145826
VI-LOG_requestIdleCallback_81 -- Current Time 145826
VI-LOG_requestIdleCallback_82 -- Current Time 145826
VI-LOG_requestIdleCallback_83 -- Current Time 145826
VI-LOG_requestIdleCallback_84 -- Current Time 145826
VI-LOG_requestIdleCallback_85 -- Current Time 145826
VI-LOG_requestIdleCallback_86 -- Current Time 145826
VI-LOG_requestIdleCallback_87 -- Current Time 145826
VI-LOG_requestIdleCallback_88 -- Current Time 145827
VI-LOG_requestIdleCallback_89 -- Current Time 145827
VI-LOG_requestIdleCallback_90 -- Current Time 145827
VI-LOG_requestIdleCallback_91 -- Current Time 145827
VI-LOG_requestIdleCallback_92 -- Current Time 145827
VI-LOG_requestIdleCallback_93 -- Current Time 145827
VI-LOG_requestIdleCallback_94 -- Current Time 145827
VI-LOG_requestIdleCallback_95 -- Current Time 145827
VI-LOG_requestIdleCallback_96 -- Current Time 145827
VI-LOG_requestIdleCallback_97 -- Current Time 145827
VI-LOG_requestIdleCallback_98 -- Current Time 145827
VI-LOG_requestIdleCallback_99 -- Current Time 145827
VI-LOG_requestIdleCallback_100 -- Current Time 145827
VI-LOG_requestIdleCallback_101 -- Current Time 145827
VI-LOG_requestIdleCallback_102 -- Current Time 145827
VI-LOG_requestIdleCallback_103 -- Current Time 145827
VI-LOG_requestIdleCallback_104 -- Current Time 145827
VI-LOG_requestIdleCallback_105 -- Current Time 145827
VI-LOG_requestIdleCallback_106 -- Current Time 145827
VI-LOG_requestIdleCallback_107 -- Current Time 145827
VI-LOG_requestIdleCallback_108 -- Current Time 145828
VI-LOG_requestIdleCallback_109 -- Current Time 145828
VI-LOG_requestIdleCallback_110 -- Current Time 145828
VI-LOG_requestIdleCallback_111 -- Current Time 145828
VI-LOG_requestIdleCallback_112 -- Current Time 145828
VI-LOG_requestIdleCallback_113 -- Current Time 145828
VI-LOG_requestIdleCallback_114 -- Current Time 145828
VI-LOG_requestIdleCallback_115 -- Current Time 145828
VI-LOG_requestIdleCallback_116 -- Current Time 145828
VI-LOG_requestIdleCallback_117 -- Current Time 145828
VI-LOG_requestIdleCallback_118 -- Current Time 145828
VI-LOG_requestIdleCallback_119 -- Current Time 145828
VI-LOG_requestIdleCallback_120 -- Current Time 145828
VI-LOG_requestIdleCallback_121 -- Current Time 145828
VI-LOG_requestIdleCallback_122 -- Current Time 145828
VI-LOG_requestIdleCallback_123 -- Current Time 145828
VI-LOG_requestIdleCallback_124 -- Current Time 145828
VI-LOG_requestIdleCallback_125 -- Current Time 145828
VI-LOG_requestIdleCallback_126 -- Current Time 145828
VI-LOG_requestIdleCallback_127 -- Current Time 145828
VI-LOG_requestIdleCallback_128 -- Current Time 145828
VI-LOG_requestIdleCallback_129 -- Current Time 145829
VI-LOG_requestIdleCallback_130 -- Current Time 145829
VI-LOG_requestIdleCallback_131 -- Current Time 145829
VI-LOG_requestIdleCallback_132 -- Current Time 145829
VI-LOG_requestIdleCallback_133 -- Current Time 145829
VI-LOG_requestIdleCallback_134 -- Current Time 145829
VI-LOG_requestIdleCallback_135 -- Current Time 145829
VI-LOG_requestIdleCallback_136 -- Current Time 145829
VI-LOG_requestIdleCallback_137 -- Current Time 145829
VI-LOG_requestIdleCallback_138 -- Current Time 145829
VI-LOG_requestIdleCallback_139 -- Current Time 145829
VI-LOG_requestIdleCallback_140 -- Current Time 145829
VI-LOG_requestIdleCallback_141 -- Current Time 145829
VI-LOG_requestIdleCallback_142 -- Current Time 145829
VI-LOG_requestIdleCallback_143 -- Current Time 145829
VI-LOG_requestIdleCallback_144 -- Current Time 145829
VI-LOG_requestIdleCallback_145 -- Current Time 145829
VI-LOG_Count: 146, Current Time: 146005
VI-LOG_requestAnimationFrame_146 -- Current Time 146006
VI-LOG_requestIdleCallback_146 -- Current Time 146007
VI-LOG_Count: 147, Current Time: 147005
VI-LOG_requestAnimationFrame_147 -- Current Time 147006
VI-LOG_requestIdleCallback_147 -- Current Time 147006
VI-LOG_Count: 148, Current Time: 148005
VI-LOG_requestAnimationFrame_148 -- Current Time 148005
VI-LOG_requestIdleCallback_148 -- Current Time 148005
VI-LOG_Count: 149, Current Time: 149005
VI-LOG_requestAnimationFrame_149 -- Current Time 149006
VI-LOG_requestIdleCallback_149 -- Current Time 149006
VI-LOG_Count: 150, Current Time: 150005
VI-LOG_requestAnimationFrame_150 -- Current Time 150005
VI-LOG_requestIdleCallback_150 -- Current Time 150005
Test1 中 15 之前聚焦 tab,15 之后切换 tab,146 重新聚焦 tab。
| exCount | 事件类型 | 时间戳 (ms) | setInterval 距离上次触发 (ms) | rAF/rIC 距离 setInterval 触发 (ms) | Tab 状态 | 备注 |
|---|---|---|---|---|---|---|
| 1 | setInterval | 1034 | - | - | Focused | |
| 1 | requestAnimationFrame | 1042 | - | 8 | Focused | |
| 1 | requestIdleCallback | 1043 | - | 9 | Focused | |
| ... | ... | ... | ~1000 | < 10ms | Focused | 行为稳定 |
| 15 | setInterval | 15002 | ~1000 | - | Focused | 切换 Tab 前最后一次 |
| 15 | requestAnimationFrame | 15003 | - | 1 | Focused | |
| 15 | requestIdleCallback | 15004 | - | 2 | Focused | |
| --- | --- TAB SWITCHED --- | --- | --- | --- | --- | --- 用户切换到其他 Tab --- |
| 16 | setInterval | 16397 | 1395 | - | Background | setInterval 被节流,rAF 未执行 |
| 16 | requestIdleCallback | 16399 | - | 2 | Background | rIC 仍然执行 |
| 17 | setInterval | 17381 | 984 | - | Background | rAF 未执行 |
| 17 | requestIdleCallback | 17382 | - | 1 | Background | rIC 仍然执行 |
| ... | ... | ... | ~1000 (不精确) | - (rAF) / ~ms (rIC) | Background | rAF 不执行, rIC 执行 |
| 145 | setInterval | 145381 | ~1000 (不精确) | - | Background | 重新聚焦 Tab 前最后一次 setInterval |
| --- | --- TAB REFOCUSED --- | --- | --- | --- | --- | --- 用户切回此 Tab --- |
| 16 | requestAnimationFrame | 145814 | - | (145814 - 16397) ~129秒后 | Refocusing | 堆积的 rAF 开始执行 (Count 16 的 rAF) |
| 17 | requestAnimationFrame | 145814 | - | (145814 - 17381) ~128秒后 | Refocusing | ... |
| ... | requestAnimationFrame | ... | - | ... | Refocusing | 所有从 Count 16 到 145 的 rAF 在 145814ms - 145821ms 间隙执行完毕 |
| 145 | requestAnimationFrame | 145821 | - | (145821 - 145381) ~440ms后 | Refocusing | Count 145 的 rAF 执行 |
| 25 | requestIdleCallback | 145822 | - | (145822 - 25376) ~120秒后 | Refocusing | 堆积的 rIC 开始执行 (Count 25 的 rIC) |
| ... | requestIdleCallback | ... | - | ... | Refocusing | 所有从 Count 16 到 145 的 rIC (未在后台及时执行的) 在 145822ms - 145829ms 间隙执行完毕 |
| 145 | requestIdleCallback | 145829 | - | (145829 - 145381) ~448ms后 | Refocusing | Count 145 的 rIC 执行 |
| 146 | setInterval | 146005 | (146005 - 145381) = 624ms | - | Focused | 恢复正常 |
| 146 | requestAnimationFrame | 146006 | - | 1 | Focused | |
| 146 | requestIdleCallback | 146007 | - | 2 | Focused | |
| ... | ... | ... | ~1000 | < 10ms | Focused | 行为恢复稳定 |
Test2 的日志输出
VP_LOG_1 - 1001
VP_LOG_2 - 1002
VP_LOG_3 - 1002
VP_LOG_4 - 1005
VP_LOG_5 - 1002
VP_LOG_6 - 1002
VP_LOG_7 - 1001
VP_LOG_8 - 1002
VP_LOG_9 - 1001
VP_LOG_10 - 1001
VP_LOG_11 - 1001
VP_LOG_12 - 1001
VP_LOG_13 - 1002
VP_LOG_14 - 1001
VP_LOG_15 - 1002
VP_LOG_16 - 2118
VP_LOG_17 - 1871
VP_LOG_18 - 1001
VP_LOG_19 - 1002
VP_LOG_20 - 1001
VP_LOG_21 - 1996
VP_LOG_22 - 1001
VP_LOG_23 - 1001
VP_LOG_24 - 1998
VP_LOG_25 - 1001
VP_LOG_26 - 1001
VP_LOG_27 - 1001
VP_LOG_28 - 1001
VP_LOG_29 - 1002
VP_LOG_30 - 1995
VP_LOG_31 - 1001
VP_LOG_32 - 1002
VP_LOG_33 - 2006
VP_LOG_34 - 1990
VP_LOG_35 - 1001
VP_LOG_36 - 1001
VP_LOG_37 - 1001
VP_LOG_38 - 1013
VP_LOG_39 - 2016
VP_LOG_40 - 1969
VP_LOG_41 - 1001
VP_LOG_42 - 1000
VP_LOG_43 - 1003
VP_LOG_44 - 1996
VP_LOG_45 - 1001
VP_LOG_46 - 1006
VP_LOG_47 - 1992
VP_LOG_48 - 1002
VP_LOG_49 - 1004
VP_LOG_50 - 1995
VP_LOG_51 - 1001
VP_LOG_52 - 1002
VP_LOG_53 - 1997
VP_LOG_54 - 1002
VP_LOG_55 - 1002
VP_LOG_56 - 1998
VP_LOG_57 - 1020
VP_LOG_58 - 1978
VP_LOG_59 - 1001
VP_LOG_60 - 1001
VP_LOG_61 - 1021
VP_LOG_62 - 1977
VP_LOG_63 - 2003
VP_LOG_64 - 1003
VP_LOG_65 - 1995
VP_LOG_66 - 1007
VP_LOG_67 - 1993
VP_LOG_68 - 1001
VP_LOG_69 - 1002
VP_LOG_70 - 1001
VP_LOG_71 - 1999
VP_LOG_72 - 2013
VP_LOG_73 - 1984
VP_LOG_74 - 1003
VP_LOG_75 - 2053
VP_LOG_76 - 1949
VP_LOG_77 - 2000
VP_LOG_78 - 1333
VP_LOG_79 - 1686
VP_LOG_80 - 1001
VP_LOG_81 - 1001
VP_LOG_82 - 1001
VP_LOG_83 - 1002
VP_LOG_84 - 1002
VP_LOG_85 - 1002
VP_LOG_86 - 1002
VP_LOG_87 - 1002
VP_LOG_88 - 1002
VP_LOG_89 - 1002
VP_LOG_90 - 1001
VP_LOG_91 - 1002
VP_LOG_92 - 1001
VP_LOG_93 - 1002
VP_LOG_94 - 1002
VP_LOG_95 - 1002
VP_LOG_96 - 1001
VP_LOG_97 - 1002
VP_LOG_98 - 1001
VP_LOG_99 - 1001
VP_LOG_100 - 1001
VP_LOG_101 - 1001
VP_LOG_102 - 1001
VP_LOG_103 - 1002
VP_LOG_104 - 1001
VP_LOG_105 - 1002
VP_LOG_106 - 1002
VP_LOG_107 - 1002
VP_LOG_108 - 1001
VP_LOG_109 - 1002
VP_LOG_110 - 1002
Test2 中 15 切 tab,80 重新聚焦 tab。
setInterval的行为:- 前台: 大致按照设定的
1000ms间隔执行,但会受主线程繁忙程度影响,不能保证精确。 - 后台: 浏览器会对其进行节流 (
throttling) 以节省CPU和 电池资源。执行间隔会变得更长且不固定。这是现代浏览器为了优化后台标签页性能的常见策略。
- 前台: 大致按照设定的
requestAnimationFrame (rAF)的行为:- 前台: 回调函数会在浏览器下一次重绘之前执行。这通常与显示器的刷新率同步(例如
60Hz对应约16.7ms一帧)。日志中,rAF在setInterval回调之后几毫秒内执行,符合预期。 - 后台: 当标签页不是激活状态时,浏览器会暂停
requestAnimationFrame的回调执行。所有通过rAF调度的回调会被加入队列,直到标签页恢复激活状态。 - 重新聚焦: 一旦标签页重新激活,所有在后台期间累积的
rAF回调会在短时间内集中执行完毕,然后再开始处理新的rAF请求。
- 前台: 回调函数会在浏览器下一次重绘之前执行。这通常与显示器的刷新率同步(例如
requestIdleCallback (rIC)的行为:- 前台: 回调函数会在浏览器主线程处于空闲时期时被调用。这允许执行一些低优先级的后台任务而不会影响用户体验(如动画流畅性)。
- 后台:
requestIdleCallback的行为与rAF不同。即使在后台,如果浏览器判断有空闲资源,rIC的回调仍然可能被执行。不过,后台rIC的执行频率和可用的timeRemaining()可能会受到限制。 - 重新聚焦: 类似于
rAF,如果在后台期间有rIC回调被调度但因某些原因(如没有足够的空闲时间或浏览器策略)未能立即执行,它们也可能在Tab重新激活后得到执行。
setTimeout的行为:前台:当页面处于前台时,链式
setTimeout的执行间隔与其设定的延迟时间 (1000ms) 非常接近。微小的偏差 (1-5ms) 是正常的,受系统负载和浏览器事件循环调度的影响。后台:现代浏览器为了优化性能和电池寿命,会对后台
Tab中的计时器(包括setTimeout和setInterval)进行节流。
小结
- 避免在后台
Tab过度依赖setInterval和setTimeout的精确性: 后台节流是标准行为。如果需要更可靠的后台任务,应考虑Web Workers或Service Workers(尽管它们也有其自身的生命周期和限制)。 - 理解
requestAnimationFrame的暂停机制: 对于依赖requestAnimationFrame的动画或 UI 更新,要意识到它们在Tab切走后会暂停,并在切回时可能出现大量堆积任务的“追赶”执行。如果这种追赶执行计算量过大,可能导致Tab切回时短暂的卡顿。应设计状态更新逻辑,使其能够平滑地从暂停状态恢复,或者在暂停期间就无需累积不必要的更新。 - 善用
requestIdleCallback: 对于非关键任务、数据同步、日志上报等,requestIdleCallback是一个很好的选择,它可以有效利用浏览器的空闲时间。但也要注意timeRemaining()和timeout选项,确保任务能在合理时间内完成或被分解。 - 页面可见性
API (Page Visibility API): 结合document.addEventListener('visibilitychange', callback)和document.hidden属性,可以明确地知道页面何时在前台、何时在后台,从而更精细地控制定时器、动画和数据请求等行为,例如在页面隐藏时主动暂停某些活动,在恢复时再继续。
通常对于浏览器这一宿主环境来说,单个事件循环 tick 中,会执行如下任务:
- 执行一个宏任务 (Task): 从宏任务队列中选择一个最旧的、可运行的宏任务并执行它。这些宏任务通常包含
setTimeout、setInterval、MessageChannel、I/O 操作、UI 交互事件等回调函数。 - 执行所有微任务 (Microtask Checkpoint): 执行当前宏任务执行完毕后存在的所有微任务。如果微任务执行过程中又添加了新的微任务,则继续执行,直到微任务队列为空。这些微任务通常包含
Promise.resolve().then(fn)、queueMicrotask(fn)、MutationObserver等回调函数。 - 更新渲染 (Update the Rendering - 按需):
- 执行所有
requestAnimationFrame (rAF)回调。 - 执行样式计算、布局、合成和绘制等渲染步骤 (如果浏览器确定需要渲染)。
- 执行所有
- 执行
requestIdleCallback回调 (按需且有空闲时间): 如果当前帧有空闲时间,并且requestIdleCallback队列中有回调,则执行它们。
可以总结为三大任务,宏任务、微任务、环境任务
接下来分析一下哪一种适合 react 的任务调度:
trade-off
requestAnimationFrame (rAF) 的可行性分析
优点:
- 与渲染同步: rAF 在浏览器下一次重绘之前执行,非常适合执行那些需要直接操作 DOM 并希望与屏幕刷新同步更新的任务。这对于 React 的 "commit phase"(将虚拟 DOM变更应用到真实 DOM)来说,是理想的执行时机,可以确保动画的流畅性和视觉更新的一致性。
- 高优先级执行: 在 Tab 激活时,rAF 的回调通常能得到及时处理。
局限性:
- 后台 Tab 暂停: 我们明确观察到,当 Tab 进入后台时,rAF 的回调会完全暂停执行。如果 React 的核心工作循环 (work loop) 完全依赖 rAF,那么在 Tab 后台时,所有 React 更新(包括状态更新、副作用处理等)都会停止。这对于某些需要后台保持一定活性的应用(如消息通知、数据预取后更新状态)是不可接受的。
- 不适合长时间计算: rAF 的回调预算非常有限(通常是 16.7ms @ 60Hz 的一部分)。React 的 "render phase"(计算组件树、diffing)可能耗时较长,如果完全放在 rAF 回调中,很容易导致掉帧和 UI 卡顿。React 需要将这些工作拆分成小块。
- 用途单一: rAF 主要关注与渲染相关的任务。React 的调度器还需要处理非渲染任务,如数据获取后的状态更新、useEffect 的执行等,这些不一定需要与帧同步。
React 中的潜在应用
- React Scheduler 确实使用类似 rAF 的机制来确保最终的 DOM commit 与浏览器的绘制步骤同步,以获得最佳的视觉性能。例如,高优先级的同步更新可能会被安排在接近 rAF 的时机提交。
requestIdleCallback (rIC) 的可行性分析
优点:
- 利用空闲时间: rIC 允许在浏览器主线程空闲时执行任务,这与 React Concurrent Mode “可中断渲染”的核心思想高度契合。deadline.timeRemaining() 机制可以帮助 React 判断当前帧有多少剩余时间可用于执行工作。
- 后台 Tab 部分执行: 测试表明,rIC 在后台 Tab 中仍有机会执行,尽管频率和可靠性可能降低。这比 rAF 的完全暂停要好,适用于一些希望在后台也能“尽力而为”处理的低优先级任务。
- 低优先级任务的理想选择: 适合处理可延迟的任务,如分析、日志记录、预渲染非可视区域内容等。
局限性:
- 执行时机不保证: rIC 的执行依赖于主线程是否空闲。如果主线程持续繁忙(例如,复杂的动画或其他脚本正在运行),rIC 回调可能长时间得不到执行,或者 timeRemaining() 始终很小。这对于需要及时响应的用户交互(如输入框反馈)或高优先级更新是不可接受的。
- timeout 选项的妥协: 虽然 rIC 提供了 timeout 选项来确保任务最终能被执行,但这在某种程度上违背了“仅在空闲时执行”的初衷,并可能在繁忙时期仍然抢占主线程资源。
- 浏览器支持和行为差异: 虽然现代浏览器普遍支持 rIC,但在细节行为和调度优先级上可能存在细微差异。
- 后台执行的不确定性: 后台 Tab 中的 rIC 执行频率更低且更不可预测,不能依赖它来完成关键的后台任务。
React 中的潜在应用:
- React Scheduler 的核心思想与 rIC 非常相似:将工作分解成小块,在有空闲时间时执行,并允许更高优先级的任务(如用户输入)中断当前工作。
- 对于低优先级的更新,例如屏幕外内容的渲染(offscreen rendering)或过渡(transitions),rIC 的模型是适用的。React 可以利用类似 rIC 的策略来安排这些任务,以便不阻塞更重要的工作。
setTimeout 的可行性分析
在聚焦 tab 时,
setTimeout(fn, 0)任务优先级高于MessageChannel。浏览器在标签页退后台后会对setTimeout(fn, 0)进行显著的节流(throttling),导致其延迟通常增加到约1s左右,当执行了12.4min左右,延迟稳定为1min左右。相比之下,MessageChannel的消息传递即便在标签页后台状态下,其回调执行相对稳定,虽非聚焦 tab 场景下偶尔会存在回调延迟问题(超过1s),但基本稳定在10ms以下。标签页重新激活后,setTimeout的响应会恢复。微任务的可行性分析
单个事件循环 tick 中,会情况所有的微任务队列。那么很重要的问题是,若
react采用微任务作为任务调度,那么react需要如何确定调度的时机呢,react不可能一次性将所有的任务推送到微任务队列中,这会缺失并发性,容易产生饥饿现象,阻塞后续浏览器的渲染流程。与此同时,并发的意义就在于可以控制单个事件循环 tick 中要执行哪些任务,但是宿主环境并没有提供单个事件循环触发的时机或者结束单个事件循环 tick 时要触发时机,对于react来说就无法通过微任务得知下一个事件循环 tick 的时机。
上述了解到,不采用环境 api(requestAnimationFrame、requestIdleCallback) 是因为调度时机上具有不确定因素,以及强依赖宿主环境;不采用微任务的原因在于无法单凭微任务而在一个事件循环 tick 中确定要处理哪些微任务;
对于宏任务来说,注册宏任务后,调度时机由浏览器来决定。当然需要注意的是一个事件循环 tick 中可能会应该繁重的渲染流程可跳过,不过幸运的是,浏览器内部会有调度策略,不会因繁重的渲染任务而持续让宏任务队列中的任务饥饿。因此将调度交付给浏览器决定是合适的,浏览器会判断什么时候可以执行宏任务,什么时候需要重点完成渲染工作,不考虑环境api(requestAnimationFrame、requestIdleCallback)
不采用微任务的原因在于微任务容易使浏览器产生饥饿现象,导致页面卡顿。在微任务中若产生其他的微任务,那么在当前的事件循环 tick 中会继续执行,这容易造成饥饿现象。而对于宏任务(MessageChannel、setTimeout)来说,在非边界的场景下,浏览器一个帧中通常会执行一个宏任务,那么这对于 react 来说可以通过控制宏任务执行的时间来控制主线程的占用,即在单位任务完成后通过判断是否还有剩余时间来决定是否将主线程交付给浏览器。若是微任务,那么react若将任务推送到微任务队列中的话