欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Nodejs的timers模塊

 更新時(shí)間:2016年12月22日 14:57:18   作者:zyl_lyr1019  
本篇文章主要介紹了Nodejs的timers模塊,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

本模塊,屬于來(lái)模擬一些瀏覽器自帶方法的模塊,比如setTimeout,clearTimeout等方法,之所以會(huì)有該模塊,在我看來(lái),也是為了能讓前端工程師使用起來(lái),更簡(jiǎn)單,使用一個(gè)單獨(dú)的模塊,來(lái)把瀏覽器上的功能來(lái)模擬出來(lái),那么就可以直接減少學(xué)習(xí)的成本,這樣就可以花更少的時(shí)間,學(xué)習(xí)到更多的東西。

timers模塊中,使用的C++的方法

timers模塊中,調(diào)用了C++實(shí)現(xiàn)的方法,這些方法,在該模塊中,占據(jù)了很重要的位置,所以,這里我們先來(lái)看下,在C++的方法中,提供了哪些方法。

var Timer = process.binding('timer_wrap').Timer; 
console.log(Timer); 

運(yùn)行之后,在控制臺(tái),就會(huì)打印出如下的內(nèi)容,它的格式如下

{ 
 [Function: Timer] 
 // Timer構(gòu)造函數(shù),可以進(jìn)行實(shí)例化 
 kOnTimeout: 0, 
 // 靜態(tài)屬性,公用,更改會(huì)影響其他的調(diào)用 
 now: [Function: now] 
 // 靜態(tài)方法,獲取類(lèi)似時(shí)間戳的一個(gè)數(shù)字 
} 

其中,Timer本身是一個(gè)構(gòu)造函數(shù),而這個(gè)構(gòu)造函數(shù)中,還包含了一個(gè)靜態(tài)屬性和一個(gè)靜態(tài)方法,關(guān)于靜態(tài)屬性和方法,基本上,這兩個(gè)只是拿來(lái)使用的,是禁止修改的,并且,其使用方法比較簡(jiǎn)單,所以這里不多說(shuō)了。
Timer既然還是一個(gè)構(gòu)造函數(shù),那么久是可以被實(shí)例化的,接下來(lái),看下實(shí)例化之后的對(duì)象:

var Timer = process.binding('timer_wrap').Timer, 
 timer = new Timer(), 
 i = ""; 
 
console.log("obj has attribute:"); 
console.log(timer); 
 
console.log("prototype method and attribute:"); 
for(i in timer){ 
 console.log(i+"="+timer[i]); 
} 

把上面的代碼,執(zhí)行的結(jié)果如下:

obj has attribute: 
{} 
 
prototype method and attribute: 
close=function close() { [native code] } 
ref=function ref() { [native code] } 
unref=function unref() { [native code] } 
start=function start() { [native code] } 
stop=function stop() { [native code] } 
setRepeat=function setRepeat() { [native code] } 
getRepeat=function getRepeat() { [native code] } 
again=function again() { [native code] } 

從上面的結(jié)果中可以看出,在Timer實(shí)例化之后,在對(duì)象本身,是沒(méi)有屬性和方法的,在原型鏈上,是有一些方法,至于這些方法,有什么用,就需要慢慢去看一下了。

timers模塊中的一個(gè)基礎(chǔ)--構(gòu)造函數(shù)Timeout

之所以這里要把這個(gè)構(gòu)造函數(shù)以單小節(jié)的形式給出,是因?yàn)樵谖铱磥?lái),如果想要對(duì)整個(gè)timers模塊中的邏輯有更好的認(rèn)識(shí),那么該模塊的基礎(chǔ)一個(gè)私有的構(gòu)造函數(shù)的理解,還是很有必要的。

這里,我們首先來(lái)看一下源碼:

var Timeout = function(after) { 
 // 定義內(nèi)部屬性,過(guò)時(shí)時(shí)間 
 this._idleTimeout = after; 
 
 // 循環(huán)鏈表中的兩個(gè)屬性,可以參考前篇文章linklist私有模塊 
 this._idlePrev = this; 
 this._idleNext = this; 
 
 // 記錄開(kāi)始計(jì)時(shí)時(shí)間的屬性 
 this._idleStart = null; 
 
 // 當(dāng)時(shí)間到了,執(zhí)行的回調(diào)函數(shù) 
 this._onTimeout = null; 
 
 // 該計(jì)時(shí)器,是否需要repeat,setInterval方法,該屬性為true 
 this._repeat = false; 
}; 
 
 
function unrefdHandle() { 
 // unref方法的回調(diào)函數(shù),內(nèi)部this指向Timeout._handle屬性 
 // 在該屬性上,定義了owner屬性,保存Timeout的實(shí)例化后的對(duì)象 
 this.owner._onTimeout(); 
 if (!this.owner._repeat) 
  this.owner.close(); 
} 
 
Timeout.prototype.unref = function() { 
 // 這個(gè)方法,是用來(lái)暫停計(jì)時(shí)器的 
 // 添加一個(gè)新的屬性_handle用來(lái)對(duì)接C++提供的API接口 
 if (!this._handle) { 
  // 做一些初始的判斷屬性,設(shè)置初始值等 
  var now = Timer.now(); 
  if (!this._idleStart) this._idleStart = now; 
  var delay = this._idleStart + this._idleTimeout - now; 
  if (delay < 0) delay = 0; 
 
  // 把this指向的計(jì)時(shí)器對(duì)象,清理掉,從計(jì)時(shí)器鏈表中清理掉 
  exports.unenroll(this); 
 
  // 介入C++提供的API方法 
  this._handle = new Timer(); 
 
  // 添加一些屬性,用來(lái)保存一些信息 
  this._handle.owner = this; 
  this._handle[kOnTimeout] = unrefdHandle; 
 
  // 開(kāi)始計(jì)時(shí),在delay后執(zhí)行改方法的回調(diào) 
  this._handle.start(delay, 0); 
  this._handle.domain = this.domain; 
 
  // 調(diào)用C++提供的方法,停止計(jì)時(shí)器的執(zhí)行 
  this._handle.unref(); 
 } else { 
  // 如果之前有_handle屬性,那么則直接停止 
  this._handle.unref(); 
 } 
}; 
 
Timeout.prototype.ref = function() { 
 // 該方法,只有在unref之后,才起作用,恢復(fù)計(jì)時(shí)器的工作 
 // 如果在unref中,生成了_handle屬性,那么使用該屬性 
 // 調(diào)用C++提供的API,ref,恢復(fù)計(jì)時(shí)器的運(yùn)行 
 if (this._handle) 
  this._handle.ref(); 
}; 
 
Timeout.prototype.close = function() { 
 // 當(dāng)要關(guān)閉計(jì)時(shí)器對(duì)象時(shí),如果定義過(guò)接入C++餓API的方法時(shí) 
 // 直接使用C++的方法,關(guān)閉 
 // 否則,把該方法,清理出去 
 // 不讓它再lists鏈表中,那么當(dāng)計(jì)時(shí)器執(zhí)行到時(shí),也不會(huì)執(zhí)行該計(jì)時(shí)器的回調(diào)函數(shù) 
 this._onTimeout = null; 
 if (this._handle) { 
  this._handle[kOnTimeout] = null; 
  // 調(diào)用C++中提供的close方法,見(jiàn)前面構(gòu)造函數(shù)Timer的原型鏈方法中 
  this._handle.close(); 
 } else { 
  exports.unenroll(this); 
 } 
}; 

上面的源碼,就是在timers模塊中,內(nèi)部的一個(gè)私有構(gòu)造函數(shù),在timers公開(kāi)的一些方法,占據(jù)了一個(gè)很重要的位子,因?yàn)?,這個(gè)方法,是timers模塊,與C++代碼鏈接的重要部分。該部分,是沒(méi)有示例可以給出的,只有在后面使用timers模塊對(duì)外公開(kāi)的API中,來(lái)看下對(duì)應(yīng)的使用效果。

這里之所以,要先把這個(gè)構(gòu)造函數(shù)放在這里,因?yàn)椋谖铱磥?lái),如果能先對(duì)這個(gè)構(gòu)造函數(shù)有所了解的話,那么接下來(lái)看timers模塊中的其他方法時(shí),就會(huì)變的簡(jiǎn)單很多。

當(dāng)然,也有可能是,因?yàn)闆](méi)有看其他的源代碼,而導(dǎo)致對(duì)于該構(gòu)造函數(shù)的一些方法和屬性,很沒(méi)用感覺(jué)的,那么,接下來(lái),就繼續(xù)看下去吧。

timers模塊的源碼

timers中的源碼,可以分為兩部分,在這里,只會(huì)看下其中的一部分,還有另外一部分,是和延時(shí)執(zhí)行相反的立即執(zhí)行的回調(diào)函數(shù),這是我們不常用到的,所以這里就不在占用篇幅。

這里,依然使用源碼來(lái)開(kāi)始:

'use strict'; 
 
// timer_wrap模塊,為底層C++實(shí)現(xiàn)的模塊 
var Timer = process.binding('timer_wrap').Timer; 
 // Timer在控制臺(tái)打印出的數(shù)據(jù)如下: 
 // {[Function: Timer] 是一個(gè)構(gòu)造函數(shù) 
 //  kOnTimeout: 0, 
 //  now: [Function: now] 
 // } 
 
// Nodejs模擬的雙向鏈表的操作模塊,請(qǐng)查看前一篇關(guān)于linklist的文章 
var L = require('_linklist'); 
 
// 斷言的管理模塊中的ok方法 
var assert = require('assert').ok; 
 
var kOnTimeout = Timer.kOnTimeout | 0; 
 
// Timeout values > TIMEOUT_MAX are set to 1. 
var TIMEOUT_MAX = 2147483647; // 2^31-1 
 
// 把timer添加到debug的模塊中,并生成一個(gè)函數(shù),命名為debug 
// 在之后,直接調(diào)用,該函數(shù),即可把官員timer的錯(cuò)誤信息,打印到控制臺(tái) 
var util = require('util'); 
var debug = util.debuglog('timer'); 
// 注,debuglog方法,應(yīng)該是最近的版本中,新添加的,因?yàn)樵谝荒昵?,剛接觸nodejs時(shí), 
// util模塊中,還沒(méi)有該方法 
 
 
// Object containing all lists, timers 
// key = time in milliseconds 
// value = list 
var lists = {}; 
 
// the main function - creates lists on demand and the watchers associated 
// with them. 
// 把item存入到一個(gè)鏈表中去,并且把msecs對(duì)應(yīng)的鏈表,存入到lists對(duì)象中去 
// lists的格式是這樣的: 
 // { 
 // "1000": 這里是一個(gè)循環(huán)鏈表,該鏈表內(nèi),包含了所有msecs=1000的list對(duì)象 
 // "2000":{} 
 // } 
 
function insert(item, msecs) { 
 // 給item定義兩個(gè)私有屬性 
 // 一個(gè)記錄當(dāng)前時(shí)間 
 item._idleStart = Timer.now(); 
 // 一個(gè)記錄毫秒時(shí)間,類(lèi)似于過(guò)期時(shí)間 
 item._idleTimeout = msecs; 
 
 // 如果定義的毫秒,是負(fù)值,則直接返回,不做后面的處理 
 if (msecs < 0) return; 
 
 var list; 
 
 // 如果該過(guò)期時(shí)間,已經(jīng)緩存在了lists對(duì)象中,則直接找到緩存的數(shù)據(jù) 
 if (lists[msecs]) { 
  list = lists[msecs]; 
 } else { 
  // 否則,執(zhí)行新建一個(gè)list數(shù)據(jù) 
  // 并把item和msecs的數(shù)據(jù)初始化到新創(chuàng)建的對(duì)象中去 
  list = new Timer(); 
  // 下面這些,就是Timer實(shí)例化之后,包含的方法 
  // close 
  // ref 
  // unref 
  // start 
  // stop 
  // setRepeat 
  // getRepeat 
  // again 
 
  // 實(shí)例化之后,調(diào)用start方法 
  list.start(msecs, 0); 
 
  // 把list對(duì)象,改為一個(gè)循環(huán)鏈表 
  L.init(list); 
 
  // 把該list添加到lists對(duì)象中緩存 
  // 并設(shè)置一些屬性,這些屬性,在其他方法中被用到 
  lists[msecs] = list; 
  list.msecs = msecs; 
  list[kOnTimeout] = listOnTimeout; 
 } 
 
 // 把item插入到list的下一個(gè)節(jié)點(diǎn)去 
 L.append(list, item); 
 assert(!L.isEmpty(list)); // list is not empty 
} 
 
// 每一個(gè)list的kOnTimeout的屬性值,應(yīng)該是一個(gè)回調(diào)函數(shù) 
// 所以,其內(nèi)部指向的是list本事 
function listOnTimeout() { 
 var msecs = this.msecs; 
 var list = this; 
 
 debug('timeout callback %d', msecs); 
 
 // 類(lèi)似一個(gè)時(shí)間戳,但是又和Date.now()的毫秒級(jí)時(shí)間戳不同,不知道是如何判斷這個(gè)的 
 var now = Timer.now(); 
 debug('now: %d', now); 
 
 var diff, first, threw; 
 
 // 當(dāng)時(shí)間到了之后,把對(duì)應(yīng)該時(shí)間的鏈表中的所有元素執(zhí)行 
 // 如果出現(xiàn)異味,則等一會(huì)再次執(zhí)行,請(qǐng)看源碼中的具體注釋 
 while (first = L.peek(list)) { 
  // If the previous iteration caused a timer to be added, 
  // update the value of "now" so that timing computations are 
  // done correctly. See test/simple/test-timers-blocking-callback.js 
  // for more information. 
  // 本處的while是,把list的所有前置列表,都處理一遍,直到list所處的鏈表中,只有l(wèi)ist時(shí)結(jié)束 
  if (now < first._idleStart) { 
   // 當(dāng)first元素,當(dāng)執(zhí)行insert時(shí),會(huì)操作_idleStart的屬性值 
   // 如果Timer.now的值,是一直增加的,那么這里為神馬會(huì)執(zhí)行? 
   // 那么又為什么要有這個(gè)判斷?只是打了一個(gè)log,難道只是為了做個(gè)通知? 
   now = Timer.now(); 
   debug('now: %d', now); 
  } 
 
  // 求這個(gè)差值?并且與list的msecs值進(jìn)行判斷 
  diff = now - first._idleStart; 
  if (diff < msecs) { 
   // 執(zhí)行到這里,那邊把list繼續(xù)延時(shí)一段時(shí)間,因?yàn)楫?dāng)前的一個(gè)item沒(méi)有被執(zhí)行 
   // 所以重新計(jì)時(shí),再執(zhí)行一次 
   list.start(msecs - diff, 0); 
   debug('%d list wait because diff is %d', msecs, diff); 
 
   // 并且直接return,結(jié)束本回調(diào)函數(shù),等待msecs-diff時(shí)間之后,再次執(zhí)行 
   return; 
  } else { 
   // 把first從它所在的鏈表中移除 
   L.remove(first); 
 
   // 我覺(jué)得,這里是在判斷,是否移除成功 
   assert(first !== L.peek(list)); 
 
   // 如果當(dāng)前的first沒(méi)有回調(diào)函數(shù),那么不需要再向下執(zhí)行,繼續(xù)while循環(huán) 
   if (!first._onTimeout) continue; 
 
   // 接下來(lái),就是執(zhí)行回調(diào)的處理了,處理的邏輯還行,看起來(lái)不算復(fù)雜 
   // 只是,有些判斷,我現(xiàn)在無(wú)法理解到,為什么要這么判斷 
 
   // v0.4 compatibility: if the timer callback throws and the 
   // domain or uncaughtException handler ignore the exception, 
   // other timers that expire on this tick should still run. 
   // 
   // https://github.com/joyent/node/issues/2631 
   var domain = first.domain; 
   if (domain && domain._disposed) 
    continue; 
 
   try { 
    if (domain) 
     domain.enter(); 
    threw = true; 
    first._onTimeout(); 
    if (domain) 
     domain.exit(); 
    threw = false; 
   } finally { 
    if (threw) { 
     // We need to continue processing after domain error handling 
     // is complete, but not by using whatever domain was left over 
     // when the timeout threw its exception. 
     var oldDomain = process.domain; 
     process.domain = null; 
     process.nextTick(function() { 
      list[kOnTimeout](); 
     }); 
     process.domain = oldDomain; 
    } 
   } 
  } 
 } 
 
 debug('%d list empty', msecs); 
 assert(L.isEmpty(list)); 
 list.close(); 
 delete lists[msecs]; 
} 
 
 
var unenroll = exports.unenroll = function(item) { 
 L.remove(item); 
 
 // _idleTimeout中保存著msecs的值, 
 // 所有可以根據(jù)該屬性,直接找到該對(duì)象在lists中的緩存數(shù)據(jù) 
 // 不過(guò),item的msecs中,也保存了list本身的msecs的 
 
 var list = lists[item._idleTimeout]; 
 // if empty then stop the watcher 
 debug('unenroll'); 
 if (list && L.isEmpty(list)) { 
  debug('unenroll: list empty'); 
  // list調(diào)用C++的接口 
  list.close(); 
  delete lists[item._idleTimeout]; 
 } 
 // if active is called later, then we want to make sure not to insert again 
 item._idleTimeout = -1; 
 // 本方法,其實(shí)就是在清理一些默認(rèn)的數(shù)據(jù)了 
 // 屬于,當(dāng)一個(gè)方法執(zhí)行完之后,把其對(duì)應(yīng)的數(shù)據(jù),都直接清理掉 
 
}; 
 
 
// Does not start the time, just sets up the members needed. 
exports.enroll = function(item, msecs) { 
 // 給item重新設(shè)置一些屬性 
 // msecs的值,需要時(shí)number類(lèi)型,并且有效的正整數(shù)和零 
 if (!util.isNumber(msecs)) { 
  throw new TypeError('msecs must be a number'); 
 } 
 
 if (msecs < 0 || !isFinite(msecs)) { 
  throw new RangeError('msecs must be a non-negative finite number'); 
 } 
 
 // if this item was already in a list somewhere 
 // then we should unenroll it from that 
 // 保證,item不會(huì)存在于兩個(gè)鏈表中, 
 // 比如,我最初把item設(shè)置為1000之后執(zhí)行,那么item在lists[1000]所在的鏈表中 
 // 接下來(lái),我又把item設(shè)置為2000之后執(zhí)行,那么就要先吧item從原來(lái)的lists[1000]的鏈表中刪除 
 // 然后,添加到lists[2000]所指向的鏈表去 
 if (item._idleNext) unenroll(item); 
 
 // Ensure that msecs fits into signed int32 
 // 保證是在最大值之內(nèi)的,否則,設(shè)置為一個(gè)系統(tǒng)設(shè)置的最大值 
 if (msecs > TIMEOUT_MAX) { 
  msecs = TIMEOUT_MAX; 
 } 
 
 // 設(shè)置信息,并初始化item本身的鏈表 
 item._idleTimeout = msecs; 
 L.init(item); 
}; 
 
 
// call this whenever the item is active (not idle) 
// it will reset its timeout. 
exports.active = function(item) { 
 // 把item插入到緩存的lists對(duì)象中, 
 // 或者把已經(jīng)存在的于對(duì)象中的item,進(jìn)行一次數(shù)據(jù)更新 
 var msecs = item._idleTimeout; 
 if (msecs >= 0) { 
  // 看上面的函數(shù),enroll可以知道,msecs是必須大于等于0的 
  var list = lists[msecs]; 
  // 如果list存在于lists中,找到對(duì)應(yīng)的鏈表 
 
  if (!list || L.isEmpty(list)) { 
   // 如果list為空,或者list為空鏈接,則執(zhí)行insert方法,創(chuàng)建一個(gè)新的鏈表 
   // 并且把該鏈表,保存到lists[msecs]中去 
   insert(item, msecs); 
  } else { 
   // 如果有,那么更新item屬性的當(dāng)前時(shí)間,把item插入到list鏈表中去 
   item._idleStart = Timer.now(); 
   L.append(list, item); 
  } 
 } 
}; 
 
 
/* 
* DOM-style timers 
*/ 
 
 
exports.setTimeout = function(callback, after) { 
 // setTimeout的實(shí)現(xiàn)源代碼 
 // 前兩個(gè)參數(shù)必須是固定的 
 var timer; 
 
 // after轉(zhuǎn)化為數(shù)字,或者NaN 
 after *= 1; // coalesce to number or NaN 
 
 // 如果不在合法范圍之內(nèi),則把a(bǔ)fter設(shè)置為1 
 if (!(after >= 1 && after <= TIMEOUT_MAX)) { 
  after = 1; // schedule on next tick, follows browser behaviour 
 } 
 
 // 根據(jù)Timerout構(gòu)造函數(shù),生成一個(gè)實(shí)例,該構(gòu)造函數(shù)完成的功能 
 // 只是創(chuàng)建一個(gè)對(duì)象,設(shè)置了一些屬性和一些方法 
 timer = new Timeout(after); 
 // 實(shí)例化后的timer包含以下內(nèi)部屬性 
 // _idleTimeout = after; 
 // _idlePrev = this; 
 // _idleNext = this; 
 // _idleStart = null; 
 // _onTimeout = null; 
 // _repeat = false; 
 // 以及一下幾個(gè)原型鏈方法 
 // unref 
 // ref 
 // close 
 
 // 如果傳入的參數(shù),小于等于2個(gè),說(shuō)明沒(méi)有多余的默認(rèn)參數(shù)傳入 
 if (arguments.length <= 2) { 
  timer._onTimeout = callback; 
 } else { 
 
  // 如果有多余的默認(rèn)參數(shù)傳入,那么就要把多余的參數(shù)緩存一下 
  // 使用閉包,重新設(shè)置一個(gè)回調(diào)函數(shù) 
  var args = Array.prototype.slice.call(arguments, 2); 
  timer._onTimeout = function() { 
   callback.apply(timer, args); 
  } 
 } 
 
 // 設(shè)置timer的domain屬性為process的domain屬性 
 // 該屬性,暫時(shí)還不知道為什么存在 
 if (process.domain) timer.domain = process.domain; 
 
 // 把timer設(shè)置為啟動(dòng),并在active中,插入到等待執(zhí)行的列表中去 
 exports.active(timer); 
 
 // 返回Timeout的實(shí)例對(duì)象,所以,可以想象setTimeout的返回值,到底有哪些屬性和方法了吧 
 return timer; 
}; 
 
 
exports.clearTimeout = function(timer) { 
 // 只有timer存在 
 // 回調(diào)存在,回調(diào)時(shí)間存在的情況下,才需要把該方法清理掉 
 // 至于為什么要判斷這些條件,請(qǐng)參考listOnTimeout方法內(nèi)部的注釋及邏輯 
 if (timer && (timer[kOnTimeout] || timer._onTimeout)) { 
  timer[kOnTimeout] = timer._onTimeout = null; 
  // 清除回調(diào),時(shí)間等屬性,然后把timer自lists鏈表中,去除掉 
  // 這樣減少在每次調(diào)用時(shí),對(duì)lists中對(duì)象的無(wú)意義的循環(huán) 
  if (timer instanceof Timeout) { 
   timer.close(); // for after === 0 
  } else { 
   exports.unenroll(timer); 
  } 
 } 
}; 
 
 
exports.setInterval = function(callback, repeat) { 
 // 前期的處理,和setTimeout方法相同,唯一不同的是,回調(diào) 
 // 在本方法中,回調(diào)之后,再添加另外一個(gè)計(jì)時(shí)器 
 // 在我看來(lái),就像是每次去調(diào)用setTimeout方法一樣 
 
 repeat *= 1; // coalesce to number or NaN 
 
 if (!(repeat >= 1 && repeat <= TIMEOUT_MAX)) { 
  repeat = 1; // schedule on next tick, follows browser behaviour 
 } 
 
 var timer = new Timeout(repeat); 
 var args = Array.prototype.slice.call(arguments, 2); 
 timer._onTimeout = wrapper; 
 timer._repeat = true; 
 
 if (process.domain) timer.domain = process.domain; 
 exports.active(timer); 
 
 return timer; 
 
 function wrapper() { 
  callback.apply(this, args); 
  // If callback called clearInterval(). 
  if (timer._repeat === false) return; 
  // If timer is unref'd (or was - it's permanently removed from the list.) 
 
  // 下面的處理,是因?yàn)樵趎et模塊中,和在本模塊中,重新啟用一個(gè)計(jì)時(shí)器的方法有區(qū)別 
  if (this._handle) { 
   // 該分支處理,應(yīng)該是為了net模塊中做的處理 
   // 在本模塊中,暫時(shí)是沒(méi)有提及到該屬性的 
   this._handle.start(repeat, 0); 
  } else { 
   // 當(dāng)前的模塊中的回調(diào)函數(shù) 
   timer._idleTimeout = repeat; 
   exports.active(timer); 
  } 
 } 
}; 
 
exports.clearInterval = function(timer) { 
 // 基本上,就是只有timer和repeat屬性存在的情況下 
 // 才表示timer對(duì)象,是出于Interval方法中, 
 // 這個(gè)時(shí)候,才去清理掉repeat屬性,然后clearTimeout的方法 
 // 清理掉該計(jì)時(shí)器 
 if (timer && timer._repeat) { 
  timer._repeat = false; 
  clearTimeout(timer); 
 } 
}; 

timers中的源碼,就是這樣了,篇幅有限,本篇到這里就結(jié)束了,接下來(lái)的一篇關(guān)于timers模塊的文章,將就本篇的源碼,結(jié)合一些示例,進(jìn)行一些說(shuō)明。

總結(jié)

像這樣的一些模塊,感覺(jué)突然不知道怎么寫(xiě)了,如果整篇的去放這個(gè)源碼,感覺(jué)這樣的文章,完全沒(méi)有意義的,這樣的話,還是應(yīng)該分開(kāi)寫(xiě)的吧。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 基于node的cli工具開(kāi)發(fā)使用詳解

    基于node的cli工具開(kāi)發(fā)使用詳解

    這篇文章主要為大家介紹了基于node的cli工具開(kāi)發(fā)使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • node.js中的url.resolve方法使用說(shuō)明

    node.js中的url.resolve方法使用說(shuō)明

    這篇文章主要介紹了node.js中的url.resolve方法使用說(shuō)明,本文介紹了url.resolve的方法說(shuō)明、語(yǔ)法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • Node.js 去掉種子(torrent)文件里的邪惡信息

    Node.js 去掉種子(torrent)文件里的邪惡信息

    torrent文件,又被稱(chēng)為種子,原來(lái)只是用于記錄 bt下載當(dāng)中所需信息的一種文件。但是隨著互聯(lián)網(wǎng)的極大發(fā)展,一些人士將一些邪惡的信息注入到了小小的 torrent文件當(dāng)中,種子從此變成了邪惡的代名詞。
    2015-03-03
  • 實(shí)例分析nodejs模塊xml2js解析xml過(guò)程中遇到的坑

    實(shí)例分析nodejs模塊xml2js解析xml過(guò)程中遇到的坑

    這篇文章主要介紹了實(shí)例分析nodejs模塊xml2js解析xml過(guò)程中遇到的坑,涉及nodejs模塊xml2js解析xml過(guò)程中parseString方法參數(shù)使用技巧,需要的朋友可以參考下
    2017-03-03
  • 在 Node.js 中使用 async 函數(shù)的方法

    在 Node.js 中使用 async 函數(shù)的方法

    利用 async 函數(shù),你可以把基于 Promise 的異步代碼寫(xiě)得就像同步代碼一樣。一旦你使用 async 關(guān)鍵字來(lái)定義了一個(gè)函數(shù),那你就可以在這個(gè)函數(shù)內(nèi)使用 await 關(guān)鍵字。下面通過(guò)本文給大家分享Node.js 中使用 async 函數(shù)的方法,一起看看吧
    2017-11-11
  • nvm安裝方法以及安裝后node不能使用解決

    nvm安裝方法以及安裝后node不能使用解決

    在我們的日常開(kāi)發(fā)中經(jīng)常會(huì)遇到這種情況,手上有好幾個(gè)項(xiàng)目,每個(gè)項(xiàng)目的需求不同,進(jìn)而不同項(xiàng)目必須依賴(lài)不同版的NodeJS運(yùn)行環(huán)境,nvm應(yīng)運(yùn)而生,這篇文章主要給大家介紹了關(guān)于nvm安裝方法以及安裝后node不能使用解決的相關(guān)資料,需要的朋友可以參考下
    2023-04-04
  • Node.js 使用遞歸實(shí)現(xiàn)遍歷文件夾中所有文件

    Node.js 使用遞歸實(shí)現(xiàn)遍歷文件夾中所有文件

    這篇文章主要介紹了Node.js使用遞歸實(shí)現(xiàn)遍歷文件夾中所有文件,需要的朋友可以參考下
    2017-09-09
  • Node.js模塊封裝及使用方法

    Node.js模塊封裝及使用方法

    這篇文章主要為大家詳細(xì)介紹了Node.js模塊封裝及使用方法,感興趣的朋友可以參考一下
    2016-03-03
  • vscode安裝教程以及配置node.js環(huán)境全過(guò)程

    vscode安裝教程以及配置node.js環(huán)境全過(guò)程

    這篇文章主要給大家介紹了關(guān)于vscode安裝教程以及配置node.js環(huán)境的相關(guān)資料,VSCode是一款由微軟開(kāi)發(fā)的輕量級(jí)編輯器,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-10-10
  • Visual?Studio?Code中npm腳本找不到圖文解決辦法

    Visual?Studio?Code中npm腳本找不到圖文解決辦法

    這篇文章主要給大家介紹了關(guān)于Visual?Studio?Code中npm腳本找不到的圖文解決辦法,做前端開(kāi)發(fā)如果項(xiàng)目達(dá)到了一定的規(guī)模就離不開(kāi)npm了,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07

最新評(píng)論