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

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

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

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

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

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

setTimeout(function() {

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

}, oneSecond);

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

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

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

                  setInterval(function() {

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

                  }, oneSecond);

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

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

setTimeout可以制定一個(gè)在將來(lái)某個(gè)時(shí)間把指定函數(shù)運(yùn)行一次的執(zhí)行計(jì)劃,比如:

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

                   var timeout_ms = 2000; // 2 seconds

                   var timeout = setTimeout(function() {

                            console.log("timed out!");

                   }, timeout_ms);

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

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

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

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

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

                   var timeoutTime = 1000; // one second

                   var timeout = setTimeout(function() {

                            console.log("timed out!");

                   }, timeoutTime);

                   clearTimeout(timeout);

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

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

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

代碼指定了兩個(gè)延時(shí)執(zhí)行的函數(shù)A和B,函數(shù)A計(jì)劃在2秒鐘后執(zhí)行,B計(jì)劃在1秒鐘后執(zhí)行,因?yàn)楹瘮?shù)B先執(zhí)行,而它取消了A的執(zhí)行計(jì)劃,因此A永遠(yuǎn)不會(huì)運(yùn)行。

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

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

下面代碼每秒會(huì)向控制臺(tái)輸出一句“tick”:

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

                   var period = 1000; // 1 second

                   setInterval(function() {

                            console.log("tick");

                   }, period);

如果你不想讓它永遠(yuǎn)運(yùn)行下去,可以用clearInterval()取消定時(shí)器。

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

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

                   var interval = setInterval(function() {

                            console.log("tick");

                   }, 1000);

                   // …

                   clearInterval(interval);

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

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

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

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

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

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

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

                   process.nextTick(function() {

                            my_expensive_computation_function();

                   });

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

堵塞事件循環(huán)

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

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

看下面堵塞事件循環(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);

這個(gè)例子里,nextTick2和timeout函數(shù)無(wú)論等待多久都沒(méi)機(jī)會(huì)運(yùn)行,因?yàn)槭录h(huán)被nextTick函數(shù)里的無(wú)限循環(huán)堵塞了,即使timeout函數(shù)被計(jì)劃在1秒鐘后執(zhí)行它也不會(huì)運(yùn)行。

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

退出事件循環(huán)

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

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

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

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

                            stream.end("my response");

                            process.nextTick(function() {

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

                            });

                   });

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

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

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

                   var interval = 1000;

                   setInterval(function() {

                            my_async_function(function() {

                                     console.log('my_async_function finished!');

                            });

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

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

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

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

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

                   var interval = 1000;

                   setInterval(function(){

                            (function my_async_function(){

                                      setTimeout(function(){

                                              console.log("1");

                                      },5000);

                           })();

                   },interval);

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

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

復(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行
 

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

小結(jié)

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

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

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

相關(guān)文章

  • PM2自動(dòng)部署代碼步驟流程總結(jié)

    PM2自動(dòng)部署代碼步驟流程總結(jié)

    這篇文章主要介紹了PM2自動(dòng)部署代碼步驟流程總結(jié),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-12-12
  • Node.js與PHP、Python的字符處理性能對(duì)比

    Node.js與PHP、Python的字符處理性能對(duì)比

    因?yàn)楹罄m(xù)考慮實(shí)現(xiàn) Fl 引擎的Node.js版本,所以對(duì)比了下Node.js和PHP的字符處理性能。發(fā)現(xiàn)Node.js真是甩了PHP幾條街啊,再測(cè)試了下Python,比PHP還慢。
    2014-07-07
  • Nodejs下使用gm圓形裁剪并合成圖片的示例

    Nodejs下使用gm圓形裁剪并合成圖片的示例

    本篇文章主要介紹了Nodejs下使用gm圓形裁剪并合成圖片的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-02-02
  • NodeJs的優(yōu)勢(shì)和適合開(kāi)發(fā)的程序

    NodeJs的優(yōu)勢(shì)和適合開(kāi)發(fā)的程序

    做頁(yè)游或webqq這樣的應(yīng)用nodejs有優(yōu)勢(shì),但如果做微博、豆瓣、facebook這樣的社交網(wǎng)絡(luò),nodejs還有優(yōu)勢(shì)嗎?另外不知道大家是什么原因選擇的nodejs?是因?yàn)閼?yīng)用需求還是對(duì)javascript這門(mén)語(yǔ)言的喜歡?
    2016-08-08
  • Nodejs中使用puppeteer控制瀏覽器中視頻播放功能

    Nodejs中使用puppeteer控制瀏覽器中視頻播放功能

    本項(xiàng)目主要功能為在瀏覽器中自動(dòng)播放視頻,并且實(shí)現(xiàn)音量控制,快進(jìn)快退,全屏控制,播放暫??刂频裙δ堋?duì)Nodejs中使用puppeteer控制瀏覽器中視頻播放功能感興趣的朋友跟隨小編一起看看吧
    2019-08-08
  • 一文帶你了解Node.js進(jìn)程管理工具PM2

    一文帶你了解Node.js進(jìn)程管理工具PM2

    Node.js進(jìn)程管理工具PM2是一個(gè)開(kāi)源的工具,用于管理和監(jiān)控Node.js應(yīng)用程序的運(yùn)行,它可以幫助您方便地啟動(dòng)、停止、重啟和監(jiān)視多個(gè)Node.js進(jìn)程,并提供了許多有用的功能,所以本文就和大家一起了解一下PM2,需要的朋友可以參考下
    2023-07-07
  • 詳解puppeteer使用代理

    詳解puppeteer使用代理

    這篇文章主要介紹了詳解puppeteer使用代理,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-12-12
  • Nodejs進(jìn)程管理模塊forever詳解

    Nodejs進(jìn)程管理模塊forever詳解

    服務(wù)器管理是系統(tǒng)上線后,必須要面對(duì)的問(wèn)題。最好有一個(gè)軟件可以提供整套的服務(wù)器運(yùn)行解決方案:要求運(yùn)行穩(wěn)定,支持高并發(fā),啟動(dòng)/停止命令簡(jiǎn)單,支持熱部署,宕機(jī)重啟,監(jiān)控界面和日志,集群環(huán)境。
    2014-06-06
  • node.js實(shí)現(xiàn)學(xué)生檔案管理

    node.js實(shí)現(xiàn)學(xué)生檔案管理

    這篇文章主要為大家詳細(xì)介紹了node.js實(shí)現(xiàn)學(xué)生檔案管理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • 詳解nodejs微信公眾號(hào)開(kāi)發(fā)——1.接入微信公眾號(hào)

    詳解nodejs微信公眾號(hào)開(kāi)發(fā)——1.接入微信公眾號(hào)

    本篇文章主要介紹了詳解nodejs微信公眾號(hào)開(kāi)發(fā)——1.接入微信公眾號(hào),非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2017-04-04

最新評(píng)論