Skip to content

Latest commit

 

History

History
31 lines (23 loc) · 1.88 KB

timer_2.md

File metadata and controls

31 lines (23 loc) · 1.88 KB

timer 运行原理

timer.js中有两个对象refedListsunrefedLists,都是用来存储timeout对象的,但区别在于这些timeout对象是否被refed(具体refed定义可以看event loop,简单来说,就是你的进程是否运行后会因为这个timeout一直运行,还是立即退出)。

refedLists存的是什么呢?举个例子:

refedLists = {
  '40': TimesList
}

TimesList = {
  _idleNext: Timeout1,
  _idlePrev: TimesList,
  _timer: TimeWrap,
  msecs: 40
}

Timeout1 = {
  _idleNext: Timout2,
  _idlePrev: TimList,
  _onTimeout: callback,
  _idleStart: TimeWrap.now(),
  _idleTimeout: 40
}

setTimeout(() => {}, 40)

当我们调用setTimeout()函数生成一个40ms的timer的时候,首先会创建一个Timeout1的timer,并将回调函数绑定到_onTimeout属性上。接下来就是启动这个timer,首先通过TimeWrap.now()得到当前的系统时间,并作为这个timer的启动时间绑定到timer上。然后去refedLists里面去寻找,是否已经创建40ms延迟的TimesList,如果没有,则创建一个。TimerList对象有一个_timer属性,这个字段绑定是一个TimeWrap的实例,这是从c++类库引入的一个计时器。传入40ms, 启动这个计时器,并且绑定listOnTimeout方法到实例的kOnTimeout属性,当40ms后,就会调用listOnTimeout方法。取出当前时间和链表第一个timer对象的_idleStart时间,做一个差值,如果小于40ms,则触发这个执行这个timer的回调,否则,将差值作为下一次的计时时间,重新启动TimeWrap这个计时器。这样做的好处就是,40ms这个链表的第一个timer是先添加的,它一定会先于之后的40ms的timer,所以,如果第一个节点没有到达时间,后边的timer一定都没有到达时间,这样就减少了遍历次数,使效率大大提高!