- Scheduler是什么,作用是什么?
- 什么是任务管理队列,什么是时间切片?
- 从调度入口函数开始一步一步分析源码。
Scheduler是什么,作用是什么?
Scheduler
是一个任务调度器,它根据任务的优先级对任务进行调度执行。在React
运行时,作为中枢控制着整个流程。Scheduler
是一个独立的包,不仅仅在React
中可以使用。
作用:为了提升用户体验,避免低优先级任务长时间占用调用栈而导致高优先级用户操作的任务无法被及时响应。
什么是任务管理队列,什么是时间切片?
任务管理队列
在Scheduler内部,维护着两个任务队列,如下:
- timerQueue:存储未过期的任务。
- taskQueue:存储已过期的任务。
如何区分任务是否过期呢?
在每一个任务当中,都有一个过期时间expirationTime
,只需要判断expirationTime
和当前时间currentTime
作比较就好。当过期时间大于当前时间,说明任务未过期,放到timerQueue,当过期时间小于当前时间,说明任务已过期,放到taskQueue。
expirationTime的依据是什么?
var expirationTime = startTime + timeout;
- startTime:任务开始时间
- timeout:任务过期时间,这个时间是根据任务优先级决定的,看下面代码:
var IMMEDIATE_PRIORITY_TIMEOUT = -1;
// Eventually times out
var USER_BLOCKING_PRIORITY_TIMEOUT = 250;
var NORMAL_PRIORITY_TIMEOUT = 5000;
var LOW_PRIORITY_TIMEOUT = 10000;
// Never times out
var IDLE_PRIORITY_TIMEOUT = maxSigned31BitInt;
var maxSigned31BitInt = 1073741823;
分为5个等级,最高级的过期时间为-1,最低则为1073741823
时间切片
通过名字我们就能知道这是把时间切分成若干片,再每个时间片中去执行任务。那么为什么需要去切分,不能一次执行吗?主要是为了性能问题,当js执行时间过长时会导致用户的操作无法及时得到反馈。为了解决这种问题,就把js执行时的任务进行分片执行了。
MessageChannel
MessageChannel
是一种web
的通信方式,是一种通道通信。具体用法如下:
var channel = new MessageChannel();
channel.port1.onmessage = (e) => {console.log(e)}
channel.port2.postMessage('Hello World')
我们可以通过port2
进行发送消息,port1
进行监听port2
发送的消息。而MessageChannel
属于宏任务,和setTimeout
一样。所以onmessage
触发的时机就是eventLoop
中的下一个宏任务。
onmessage
函数每次执行都是一个时间切片,在react规定了5ms
的执行时间,当react
当中的任务执行超过5s
时,就会调用postMessage
发送消息,同时停止下个任务的执行,剩下的react
任务只能再下次宏任务中执行了。