Node.js 指南(Node.js中的定時器)

Node.js中的定時器

Node.js中的Timers模塊包含在一段時間後執行代碼的函數,定時器不須要經過require()導入,由於全部方法均可以在全局範圍內模擬瀏覽器JavaScript API,要徹底瞭解什麼時候執行定時器功能,最好先閱讀Node.js事件循環segmentfault

用Node.js控制時間連續性

Node.js API提供了幾種調度代碼的方法,以便在當前時刻以後的某個時刻執行,下面的函數可能看起來很熟悉,由於它們在大多數瀏覽器中均可用,但Node.js實際上提供了這些方法的本身的實現,定時器與系統緊密集成,儘管API鏡像了瀏覽器API,但實現方面存在一些差別。瀏覽器

「我說的時候」執行 ~ setTimeout()

setTimeout()可用於在指定的毫秒數後調度代碼執行,此函數相似於瀏覽器JavaScript API中的window.setTimeout(),可是沒法傳遞一串代碼來執行。ide

setTimeout()接受一個函數做爲第一個參數執行,毫秒延遲定義爲一個數字做爲第二個參數,還能夠包括其餘參數,並將這些參數傳遞給函數,這是一個例子:函數

function myFunc(arg) {
  console.log(`arg was => ${arg}`);
}

setTimeout(myFunc, 1500, 'funky');

因爲調用了setTimeout(),上面的函數myFunc()將盡量接近1500毫秒(或1.5秒)執行。性能

設置的超時間隔不能依賴於在該精確的毫秒數以後執行,這是由於阻塞或保留在事件循環上的其餘執行代碼將推遲執行超時,惟一的保證是超時不會比聲明的超時間隔更早執行。ui

setTimeout()返回一個Timeout對象,該對象可用於引用已設置的超時,此返回的對象可用於取消超時(請參閱下面的clearTimeout())以及更改執行行爲(請參閱下面的unref())。this

「在此以後」執行 ~ setImmediate()

setImmediate()將在當前事件循環週期結束時執行代碼,此代碼將在當前事件循環中的任何I/O操做以後以及爲下一個事件循環調度的任何計時器以前執行,這個代碼執行能夠被認爲是「正好在此以後」,這意味着setImmediate()函數調用以後的任何代碼都將在setImmediate()函數參數以前執行。code

setImmediate()的第一個參數將是要執行的函數,任何後續參數將在執行時傳遞給函數,這是一個例子:對象

console.log('before immediate');

setImmediate((arg) => {
  console.log(`executing immediate: ${arg}`);
}, 'so immediate');

console.log('after immediate');

傳遞給setImmediate()的上述函數將在全部可運行代碼執行後執行,控制檯輸出將爲:進程

before immediate
after immediate
executing immediate: so immediate

setImmediate()返回一個Immediate對象,可用於取消已調度的immediate(請參閱下面的clearImmediate())。

注意:不要混淆setImmediate()process.nextTick(),它們有一些主要的不一樣之處,第一個是process.nextTick()將在任何設置的Immediate以前以及任何調度的I/O以前運行,第二個是process.nextTick()是不可清除的,意思是一旦代碼被安排用process.nextTick()執行,就沒法中止執行,就像使用普通函數同樣,請參閱本指南以更好地理解process.nextTick()的操做。

「無限循環」執行 ~ setInterval()

若是存在應該屢次執行的代碼塊,則可使用setInterval()來執行該代碼,setInterval()接受一個函數參數,它將以給定的毫秒延遲做爲第二個參數運行無限次,就像setTimeout()同樣,能夠在延遲以外添加其餘參數,並將這些參數傳遞給函數調用。也像setTimeout()同樣,因爲可能保留在事件循環上的操做,所以沒法保證延遲,所以應將其視爲近似延遲,見下面的例子:

function intervalFunc() {
  console.log('Cant stop me now!');
}

setInterval(intervalFunc, 1500);

在上面的例子中,intervalFunc()大約每1500毫秒或1.5秒執行一次,直到它被中止爲止(見下文)。

setTimeout()同樣,setInterval()也返回一個Timeout對象,該對象可用於引用和修改已設置的間隔。

清除將來

若是須要取消TimeoutImmediate對象,能夠作些什麼?setTimeout()setImmediate()setInterval()返回一個可用於引用設置TimeoutImmediate對象的計時器對象,經過將所述對象傳遞到相應的clear函數,將徹底中止該對象的執行。相應的函數是clearTimeout()clearImmediate()clearInterval(),請參閱下面的示例,瞭解每一個示例:

const timeoutObj = setTimeout(() => {
  console.log('timeout beyond time');
}, 1500);

const immediateObj = setImmediate(() => {
  console.log('immediately executing immediate');
});

const intervalObj = setInterval(() => {
  console.log('interviewing the interval');
}, 500);

clearTimeout(timeoutObj);
clearImmediate(immediateObj);
clearInterval(intervalObj);

留下超時

請記住,setTimeoutsetInterval返回Timeout對象,Timeout對象提供了兩個函數,旨在使用unref()ref()來加強Timeout行爲。若是使用set函數調度Timeout對象,則能夠在該對象上調用unref(),這將稍微改變行爲,若是它是要執行的最後一個代碼,則不會調用Timeout對象,Timeout對象不會使進程保持活動狀態,等待執行。

以相似的方式,調用了unref()Timeout對象能夠經過在同一個Timeout對象上調用ref()來刪除該行爲,而後確保其執行。但請注意,出於性能緣由,這並不能徹底恢復初始行爲,請參閱如下兩個示例:

const timerObj = setTimeout(() => {
  console.log('will i run?');
});

// if left alone, this statement will keep the above
// timeout from running, since the timeout will be the only
// thing keeping the program from exiting
timerObj.unref();

// we can bring it back to life by calling ref() inside
// an immediate
setImmediate(() => {
  timerObj.ref();
});

進一步瞭解事件循環

事件循環和計時器比本指南所涵蓋的要多得多,要了解有關Node.js事件循環內部以及計時器在執行期間如何操做的更多信息,請查看此Node.js指南:Node.js事件循環、定時器和process.nextTick()


上一篇:不要阻塞事件循環(或工做池)

下一篇:HTTP事務的剖析

相關文章
相關標籤/搜索