最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Node.js中使用計時器定時執(zhí)行函數(shù)詳解

 更新時間:2014年08月15日 11:53:51   作者:Jack Yao''s Workshop  
這篇文章主要介紹了Node.js中使用計時器定時執(zhí)行函數(shù)詳解,本文使用了Node.js中的setTimeout和setInterval函數(shù),需要的朋友可以參考下

如果你熟悉客戶端JavaScript編程,你可能使用過setTimeout和setInterval函數(shù),這兩個函數(shù)允許延時一段時間再運行函數(shù)。比如下面的代碼, 一旦被加載到Web頁面,1秒后會在頁面文檔后追加“Hello there”:

復(fù)制代碼 代碼如下:

var oneSecond = 1000 * 1; // one second = 1000 x 1 ms

setTimeout(function() {

    document.write('<p>Hello there.</p>');

}, oneSecond);

而setInterval允許以指定的時間間隔重復(fù)執(zhí)行函數(shù)。如果把下面的代碼注入到Web頁面,會導(dǎo)致每秒鐘向頁面文檔后面追加一句“Hello there”:

復(fù)制代碼 代碼如下:

                  var oneSecond = 1000 * 1; // one second = 1000 x 1 ms

                  setInterval(function() {

                                    document.write('<p>Hello there.</p>');

                  }, oneSecond);

因為Web早已成為一個用來構(gòu)建應(yīng)用程序的平臺,而不再是簡單的靜態(tài)頁面,所以這種類似的需求日益浮現(xiàn)。這些任務(wù)計劃函數(shù)幫助開發(fā)人員實現(xiàn)表單定期驗證,延遲遠程數(shù)據(jù)同步,或者那些需要延時反應(yīng)的UI交互。Node也完整實現(xiàn)了這些方法。在服務(wù)器端,你可以用它們來重復(fù)或延遲執(zhí)行很多任務(wù),比如緩存過期,連接池清理,會話過期,輪詢等等。

使用setTimeout延遲函數(shù)執(zhí)行

setTimeout可以制定一個在將來某個時間把指定函數(shù)運行一次的執(zhí)行計劃,比如:

復(fù)制代碼 代碼如下:

                   var timeout_ms = 2000; // 2 seconds

                   var timeout = setTimeout(function() {

                            console.log("timed out!");

                   }, timeout_ms);

和客戶端JavaScript完全一樣,setTimeout接受兩個參數(shù),第一個參數(shù)是需要被延遲的函數(shù),第二個參數(shù)是延遲時間(以毫秒為單位)。

setTimeout返回一個超時句柄,它是個內(nèi)部對象,可以用它作為參數(shù)調(diào)用clearTimeout來取消計時器,除此之外這個句柄沒有任何作用。

使用clearTimeout取消執(zhí)行計劃

一旦獲得了超時句柄,就可以用clearTimeout來取消函數(shù)執(zhí)行計劃,像這樣:

復(fù)制代碼 代碼如下:

                   var timeoutTime = 1000; // one second

                   var timeout = setTimeout(function() {

                            console.log("timed out!");

                   }, timeoutTime);

                   clearTimeout(timeout);

 這個例子里,計時器永遠不會被觸發(fā),也不會輸出”time out!”這幾個字。你也可以在將來的任何時間取消執(zhí)行計劃,就像下面的例子:

復(fù)制代碼 代碼如下:

 var timeout = setTimeout(function A() {
 
                            console.log("timed out!");
 
                   }, 2000);
 
                   setTimeout(function B() {
 
                            clearTimeout(timeout);
 
                   }, 1000);

代碼指定了兩個延時執(zhí)行的函數(shù)A和B,函數(shù)A計劃在2秒鐘后執(zhí)行,B計劃在1秒鐘后執(zhí)行,因為函數(shù)B先執(zhí)行,而它取消了A的執(zhí)行計劃,因此A永遠不會運行。

制定和取消函數(shù)的重復(fù)執(zhí)行計劃

setInterval和setTimeout類似,但是它會以指定時間為間隔重復(fù)執(zhí)行一個函數(shù)。你可以用它來周期性的觸發(fā)一段程序,來完成一些類似清理,收集,日志,獲取數(shù)據(jù),輪詢等其它需要重復(fù)執(zhí)行的任務(wù)。

下面代碼每秒會向控制臺輸出一句“tick”:

復(fù)制代碼 代碼如下:

                   var period = 1000; // 1 second

                   setInterval(function() {

                            console.log("tick");

                   }, period);

如果你不想讓它永遠運行下去,可以用clearInterval()取消定時器。

setInterval返回一個執(zhí)行計劃句柄,可以把它用作clearInterval的參數(shù)來取消執(zhí)行計劃:

復(fù)制代碼 代碼如下:

                   var interval = setInterval(function() {

                            console.log("tick");

                   }, 1000);

                   // …

                   clearInterval(interval);

使用process.nextTick將函數(shù)執(zhí)行延遲到事件循環(huán)的下一輪

有時候客戶端JavaScript程序員用setTimeout(callback,0)將任務(wù)延遲一段很短的時間,第二個參數(shù)是0毫秒,它告訴JavaScript運行時,當所有掛起的事件處理完畢后立刻執(zhí)行這個回調(diào)函數(shù)。有時候這種技術(shù)被用來延遲執(zhí)行一些并不需要被立刻執(zhí)行的操作。比如,有時候需要在用戶事件處理完畢后再開始播放動畫或者做一些其它的計算。

Node中,就像 “事件循環(huán)”的字面意思,事件循環(huán)運行在一個處理事件隊列的循環(huán)里,事件循環(huán)工作過程中的每一輪就稱為一個tick。

你可以在事件循環(huán)每次開始下一輪(下一個tick)執(zhí)行時調(diào)用回調(diào)函數(shù)一次,這也正是process.nextTick的原理,而setTimeout,setTimeout使用JavaScript運行時內(nèi)部的執(zhí)行隊列,而不是使用事件循環(huán)。

通過使用process.nextTick(callback) ,而不是setTimeout(callback, 0),你的回調(diào)函數(shù)會在隊列內(nèi)的事件處理完畢后立刻執(zhí)行,它要比JavaScript的超時隊列快很多(以CPU時間來衡量)。

你可以像下面這樣,把函數(shù)延遲到下一輪事件循環(huán)再運行:

復(fù)制代碼 代碼如下:

                   process.nextTick(function() {

                            my_expensive_computation_function();

                   });

  注意:process對象是Node為數(shù)不多的全局對象之一。

堵塞事件循環(huán)

Node和JavaScript的運行時采用的是單線程事件循環(huán),每次循環(huán),運行時通過調(diào)用相關(guān)回調(diào)函數(shù)來處理隊列內(nèi)的下個事件。當事件執(zhí)行完畢,事件循環(huán)取得執(zhí)行結(jié)果并處理下個事件,如此反復(fù),直到事件隊列為空。如果其中一個回調(diào)函數(shù)運行時占用了很長時間,事件循環(huán)在那期間就不能處理其它掛起的事件,這會讓應(yīng)用程序或服務(wù)變得非常慢。

在處理事件時,如果使用了內(nèi)存敏感或者處理器敏感的函數(shù),會導(dǎo)致事件循環(huán)變得緩慢,而且造成大量事件堆積,不能被及時處理,甚至堵塞隊列。

看下面堵塞事件循環(huán)的例子:

復(fù)制代碼 代碼如下:

                   process.nextTick(function nextTick1() {

                            var a = 0;

                            while(true) {

                                     a ++;

                            }

                   });

                   process.nextTick(function nextTick2() {

                            console.log("next tick");

                   });

                   setTimeout(function timeout() {

                            console.log("timeout");

                   }, 1000);

這個例子里,nextTick2和timeout函數(shù)無論等待多久都沒機會運行,因為事件循環(huán)被nextTick函數(shù)里的無限循環(huán)堵塞了,即使timeout函數(shù)被計劃在1秒鐘后執(zhí)行它也不會運行。

         當使用setTimeout時,回調(diào)函數(shù)會被添加到執(zhí)行計劃隊列,而在這個例子里它們甚至不會被添加到隊列。這雖然是個極端例子,但是你可以看到,運行一個處理器敏感的任務(wù)時可能會堵塞或者拖慢事件循環(huán)。

退出事件循環(huán)

使用process.nextTick,可以把一個非關(guān)鍵性的任務(wù)推遲到事件循環(huán)的下一輪(tick)再執(zhí)行,這樣可以釋放事件循環(huán),讓它可以繼續(xù)執(zhí)行其它掛起的事件。

看下面例子,如果你打算刪除一個臨時文件,但是又不想讓data事件的回調(diào)函數(shù)等待這個IO操作,你可以這樣延遲它:

復(fù)制代碼 代碼如下:

                   stream.on("data", function(data) {

                            stream.end("my response");

                            process.nextTick(function() {

                                     fs.unlink("/path/to/file");

                            });

                   });

使用setTimeout替代setInterval來確保函數(shù)執(zhí)行的串行性

假設(shè),你打算設(shè)計一個叫my_async_function的函數(shù),它可以做某些I/O操作(比如解析日志文件)的函數(shù),并打算讓它周期性執(zhí)行,你可以用setInterval這樣實現(xiàn)它:

復(fù)制代碼 代碼如下:

                   var interval = 1000;

                   setInterval(function() {

                            my_async_function(function() {

                                     console.log('my_async_function finished!');

                            });

                   },interval);//譯者注:前面“,interval”是我添加的,作者應(yīng)該是筆誤遺漏了

你必須能確保這些函數(shù)不會被同時執(zhí)行,但是如果使用setinterval你無法保證這一點,假如my_async_function函數(shù)運行的時間比interval變量多了一毫秒,它們就會被同時執(zhí)行,而不是按次序串行執(zhí)行。

譯者注:(下面粗體部分為譯者添加,非原書內(nèi)容)

為了方便理解這部分內(nèi)容,可以修改下作者的代碼,讓它可以實際運行:

復(fù)制代碼 代碼如下:

                   var interval = 1000;

                   setInterval(function(){

                            (function my_async_function(){

                                      setTimeout(function(){

                                              console.log("1");

                                      },5000);

                           })();

                   },interval);

 運行下這段代碼看看,你會發(fā)現(xiàn),等待5秒鐘后,“hello ”被每隔1秒輸出一次。而我們期望是,當前my_async_function執(zhí)行完畢(耗費5秒)后,等待1秒再執(zhí)行下一個my_async_function,每次輸出之間應(yīng)該間隔6秒才對。造成這種結(jié)果,是因為my_async_function不是串行執(zhí)行的,而是多個在同時運行。

 因此,你需要一種辦法來強制使一個my_async_function執(zhí)行結(jié)束到下個my_async_function開始執(zhí)行之間的間隔時間正好是interval變量指定的時間。你可以這樣做:
 

復(fù)制代碼 代碼如下:

                    var interval = 1000; // 1 秒

                   (function schedule() {      //第3行

                            setTimeout(function do_it() {

                                     my_async_function(function() {      //第5行

                                               console.log('async is done!');

                                               schedule();

                                     });

                            }, interval);

                   }());        //第10行
 

前面代碼里,聲明了一個叫schedule的函數(shù)(第3行),并且在聲明后立刻調(diào)用它(第10行),schedule函數(shù)會在1秒(由interval指定)后運行do_it函數(shù)。1秒鐘過后,第5行的my_async_function函數(shù)會被調(diào)用,當它執(zhí)行完畢后,會調(diào)用它自己的那個匿名回調(diào)函數(shù)(第6行),而這個匿名回調(diào)函數(shù)又會再次重置do_it的執(zhí)行計劃,讓它1秒鐘后重新執(zhí)行,這樣代碼就開始串行地不斷循環(huán)執(zhí)行了。

小結(jié)

可以用setTimeout()函數(shù)預(yù)先設(shè)定函數(shù)的執(zhí)行計劃,并用clearTimeout()函數(shù)取消它。還可以用setInterval()周期性的重復(fù)執(zhí)行某個函數(shù),相應(yīng)的,可以使用clearInterval()取消這個重復(fù)執(zhí)行計劃。

如果因為使用了一個處理器敏感的操作而堵塞了事件循環(huán),那些原計劃應(yīng)該被執(zhí)行的函數(shù)將會被延遲,甚至永遠無法執(zhí)行。所以不要在事件循環(huán)內(nèi)使用CPU敏感的操作。還有,你可以使用process.nextTick()把函數(shù)的執(zhí)行延遲到事件循環(huán)的下一輪。

I/O和setInterval()一起使用時,你無法保證在任何時間點只有一個掛起的調(diào)用,但是,你可以使用遞歸函數(shù)和setTimeout()函數(shù)來回避這個棘手的問題。

相關(guān)文章

  • 10個Node.js庫幫助你優(yōu)化代碼和簡化開發(fā)

    10個Node.js庫幫助你優(yōu)化代碼和簡化開發(fā)

    這篇文章主要介紹了10個Node.js庫幫助你優(yōu)化代碼和簡化開發(fā),其中包括處理數(shù)組、對象、字符串庫Lodash,緩存數(shù)據(jù)處理庫Node-cache,解析、操作和格式化日期和時間庫Moment.js,Redis操作庫,發(fā)送電子郵件庫Nodemailer
    2023-05-05
  • 開箱即用的Node.js+Mysql模塊封裝實現(xiàn)詳解

    開箱即用的Node.js+Mysql模塊封裝實現(xiàn)詳解

    這篇文章主要為大家介紹了開箱即用的Node.js+Mysql模塊封裝實現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • Nodejs使用dgram模塊創(chuàng)建UDP服務(wù)詳解

    Nodejs使用dgram模塊創(chuàng)建UDP服務(wù)詳解

    這篇文章主要為大家介紹了Nodejs使用dgram模塊創(chuàng)建UDP服務(wù)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • autojs的nodejs打包成品app經(jīng)驗分享

    autojs的nodejs打包成品app經(jīng)驗分享

    這篇文章主要為大家介紹了autojs的nodejs打包成品app經(jīng)驗分享,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • Node.js + express實現(xiàn)上傳大文件的方法分析【圖片、文本文件】

    Node.js + express實現(xiàn)上傳大文件的方法分析【圖片、文本文件】

    這篇文章主要介紹了Node.js + express實現(xiàn)上傳大文件的方法,結(jié)合實例形式分析了Node.js + express針對圖片、文本文件上傳操作實現(xiàn)方法及相關(guān)操作注意事項,需要的朋友可以參考下
    2019-03-03
  • Node.js API詳解之 tty功能與用法實例分析

    Node.js API詳解之 tty功能與用法實例分析

    這篇文章主要介紹了Node.js API詳解之 tty功能與用法,結(jié)合實例形式分析了Node.js API中tty的基本功能、用法及終端操作相關(guān)使用技巧,需要的朋友可以參考下
    2020-04-04
  • node.js中的fs.open方法使用說明

    node.js中的fs.open方法使用說明

    這篇文章主要介紹了node.js中的fs.open方法使用說明,本文介紹了fs.open方法說明、語法、接收參數(shù)、使用實例和實現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • node.js學(xué)習(xí)之事件模塊Events的使用示例

    node.js學(xué)習(xí)之事件模塊Events的使用示例

    Nodejs中不存在瀏覽器中冒泡,捕獲這些行為,Nodejs中實現(xiàn)了events這個模塊,Nodejs中大多數(shù)模塊都集成了這個模塊,所以events是Nodejs中最重要的一個模塊。這篇文章主要給大家介紹了關(guān)于node.js學(xué)習(xí)教程之事件模塊Events的相關(guān)資料,需要的朋友可以參考下。
    2017-09-09
  • Nodejs異步回調(diào)的優(yōu)雅處理方法

    Nodejs異步回調(diào)的優(yōu)雅處理方法

    這篇文章主要介紹了Nodejs異步回調(diào)的優(yōu)雅處理方法,本文使用了ES6中的新特性,用一種十分優(yōu)雅的方式解決了回調(diào)問題,需要的朋友可以參考下
    2014-09-09
  • 在node.js中怎么屏蔽掉favicon.ico的請求

    在node.js中怎么屏蔽掉favicon.ico的請求

    這篇文章主要介紹了在node.js中怎么屏蔽掉favicon.ico的請求,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-03-03

最新評論

紫金县| 阿勒泰市| 万荣县| 石渠县| 安远县| 兰溪市| 黑龙江省| 尤溪县| 海林市| 南雄市| 金沙县| 西丰县| 龙南县| 白水县| 明溪县| 洛扎县| 凤台县| 新丰县| 宾川县| 浮山县| 牡丹江市| 湘潭市| 丹阳市| 和林格尔县| 民丰县| 阳原县| 伊金霍洛旗| 绍兴市| 吉水县| 长宁县| 舒兰市| 星座| 鄂伦春自治旗| 芦山县| 潜江市| 龙泉市| 祥云县| 文安县| 凭祥市| 阳高县| 新丰县|