深入出不来nodejs源码-timer模块(JS篇)

  鸽了好久,最近沉迷游戏,继续写点什么吧,也不知道有没有人看。

  其实这个node的源码也不知道该怎么写了,很多模块涉及的东西比较深,JS和C++两头看,中间被工作耽搁回来就一脸懵逼了,所以还是挑一些简单的吧!

  

  这一篇选的是定时器模块,简单讲就是初学者都非常熟悉的setTimeout与setInterval啦,源码的JS内容在目录lib/timers.js中。

  node的定时器模块是自己单独实现的,与Chrome的window.setTimeout可能不太一样,但是思想应该都是相通的,学一学总没错。

 

链表

  定时器模块实现中有一个关键数据结构:链表。用JS实现的链表,大体上跟其他语言的链表的原理还是一样,每一个节点内容可分为前指针、后指针、数据。

  源码里的链表构造函数有两种,一个是List的容器,一个是容器里的item。

  这里看看List:

复制代码
function TimersList(msecs, unrefed) {   // 前指针  this._idleNext = this;   // 后指针  this._idlePrev = this;    // 数据  this._unrefed = unrefed;   this.msecs = msecs;   // ...更多}
复制代码

  这是一个很典型的链表例子,包含2个指针(属性)以及数据块。item的构造函数大同小异,也是包含了两个指针,只是数据内容有些不同。

  关于链表的操作,放在了一个单独的JS文件中,目录在lib/internal/linkedlist.js,实现跟C++、Java内置的有些许不一样。

  看一下增删就差不多了,首先看删:

复制代码
function remove(item) {   // 处理前后节点的指针指向  if (item._idleNext) {     item._idleNext._idlePrev = item._idlePrev;   }    if (item._idlePrev) {     item._idlePrev._idleNext = item._idleNext;   }    // 重置节点自身指针指向  item._idleNext = null;   item._idlePrev = null; }
复制代码

  关于数据结构的代码,都是虽然看起来少,但是理解起来都有点恶心,能画出图就差不多了,所以这里给一个简单的示意图。

  应该能看懂吧……反正中间那个假设就是item,首先让前后两个对接上,然后把自身的指针置null。

  接下来是增。

复制代码
function append(list, item) {   // 先保证传入节点是空白节点  if (item._idleNext || item._idlePrev) {     remove(item);   }    // 处理新节点的头尾链接  item._idleNext = list._idleNext;   item._idlePrev = list;    // 处理list的前指针指向  list._idleNext._idlePrev = item;   list._idleNext = item; }
复制代码

  这里需要注意,初始化的时候就有一个List节点,该节点只作为链表头,与其余item不一样,一开始前后指针均指向自己。

  以上是append节点的三步示例图。

  之前说过JS实现的链表与C++、Java有些许不一样,就在这里,每一次添加新节点时:

C++/Java:node-node => node-node-new

JS(node):list-node-node => list-new-node-node

  总的来说,JS用了一个list来作为链表头,每一次添加节点都是往前面塞,整体来讲是一个双向循环链表。

  而在C++/Java中则是可以选择,API丰富多彩,链表类型也分为单向、单向循环、双向等。

 

setTimeout

关键字:
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信