定時器

定時器

JavaScript提供定時執(zhí)行代碼的功能,叫做定時器(timer),主要由setTimeout()和setInterval()這兩個函數(shù)來完成。

setTimeout()

setTimeout函數(shù)用來指定某個函數(shù)或某段代碼,在多少毫秒之后執(zhí)行。它返回一個整數(shù),表示定時器的編號,以后可以用來取消這個定時器。

var timerId = setTimeout(func|code, delay)

上面代碼中,setTimeout函數(shù)接受兩個參數(shù),第一個參數(shù)func|code是將要推遲執(zhí)行的函數(shù)名或者一段代碼,第二個參數(shù)delay是推遲執(zhí)行的毫秒數(shù)。變量timerId保存著定時器的編號值。

console.log(1);
setTimeout('console.log(2)',1000);
console.log(3);

上面代碼的輸出結(jié)果就是1,3,2,因?yàn)閟etTimeout指定第二行語句推遲1000毫秒再執(zhí)行。

需要注意的是,推遲執(zhí)行的代碼必須以字符串的形式,放入setTimeout,因?yàn)橐鎯?nèi)部使用eval函數(shù),將字符串轉(zhuǎn)為代碼。如果推遲執(zhí)行的是函數(shù),則可以直接將函數(shù)名,放入setTimeout。一方面eval函數(shù)有安全顧慮,另一方面為了便于JavaScript引擎優(yōu)化代碼,setTimeout方法一般總是采用函數(shù)名的形式,就像下面這樣。

function f(){
  console.log(2);
}

setTimeout(f,1000);

// 或者

setTimeout(function (){console.log(2)},1000);

setInterval()

setInterval函數(shù)的用法與setTimeout完全一致,區(qū)別僅僅在于setInterval指定某個任務(wù)每隔一段時間就執(zhí)行一次,也就是無限次的定時執(zhí)行。

  var timer = setInterval(function() {
    console.log(2);
  }, 1000);

上面代碼表示每隔1000毫秒就輸出一個2,直到用戶點(diǎn)擊了停止按鈕。

clearTimeout(),clearInterval()

setTimeout和setInterval函數(shù),都返回一個表示計(jì)數(shù)器編號的整數(shù)值,將該整數(shù)傳入clearTimeout和clearInterval函數(shù),就可以取消對應(yīng)的定時器。

var id1 = setTimeout(f,1000);
var id2 = setInterval(f,1000);

clearTimeout(id1);
clearInterval(id2);

運(yùn)行機(jī)制

setTimeout和setInterval的運(yùn)行機(jī)制是,將指定的代碼移出本次執(zhí)行,等到下一輪 Event Loop 時,再檢查是否到了指定時間。如果到了,就執(zhí)行對應(yīng)的代碼;如果不到,就等到再下一輪 Event Loop 時重新判斷。

這意味著,setTimeout和setInterval指定的代碼,必須等到本輪 Event Loop 的所有任務(wù)都執(zhí)行完,才會開始執(zhí)行。由于前面的任務(wù)到底需要多少時間執(zhí)行完,是不確定的,所以沒有辦法保證,setTimeout和setInterval指定的任務(wù),一定會按照預(yù)定時間執(zhí)行。

setTimeout(someTask, 100);
veryLongTask();

上面代碼的setTimeout,指定100毫秒以后運(yùn)行一個任務(wù)。但是,如果后面的veryLongTask函數(shù)(同步任務(wù))運(yùn)行時間非常長,過了100毫秒還無法結(jié)束,那么被推遲運(yùn)行的someTask就只有等著,等到veryLongTask運(yùn)行結(jié)束,才輪到它執(zhí)行。

下面是setInterval的例子。

setInterval(function () {
  console.log(2);
}, 1000);

sleep(3000);//需要3000毫秒才能執(zhí)行完成

上面的第一行語句要求每隔1000毫秒,就輸出一個2。但是,緊接著的語句需要3000毫秒才能完成,那么setInterval就必須推遲到3000毫秒之后才開始生效。這3000毫秒之內(nèi),setInterval不會產(chǎn)生累積效應(yīng)。

setTimeout(f, 0)指定的任務(wù),最早也要到下一次Event Loop才會執(zhí)行。請看下面的例子。

setTimeout(function() {
  console.log("Timeout");
}, 0);

function a(x) {
  console.log("a() 開始運(yùn)行");
  b(x);
  console.log("a() 結(jié)束運(yùn)行");
}

function b(y) {
  console.log("b() 開始運(yùn)行");
  console.log("傳入的值為" + y);
  console.log("b() 結(jié)束運(yùn)行");
}

console.log("當(dāng)前任務(wù)開始");
a(42);
console.log("當(dāng)前任務(wù)結(jié)束");

// 當(dāng)前任務(wù)開始
// a() 開始運(yùn)行
// b() 開始運(yùn)行
// 傳入的值為42
// b() 結(jié)束運(yùn)行
// a() 結(jié)束運(yùn)行
// 當(dāng)前任務(wù)結(jié)束
// Timeout

上面代碼說明,setTimeout(f, 0)必須要等到當(dāng)前腳本的所有同步任務(wù)結(jié)束后才會執(zhí)行。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 定時器 參考鏈接 setTimeout() 上面代碼的輸出結(jié)果就是1,3,2,因?yàn)閟etTimeout指定第二行語...
    Cause_XL閱讀 483評論 0 0
  • 原文地址:→傳送門 寫在前面 setTimeout()是大家再熟悉不過的定時器,但平時對定時器的了解甚少,于是想看...
    樓心漫閱讀 1,638評論 3 6
  • JavaScript提供定時執(zhí)行代碼的功能,叫做定時器(timer),主要由setTimeout()和setInt...
    PYFang閱讀 267評論 0 0
  • 在javascript中,定時器有兩種,一種是setTimeout(),還有一種的setTimeout() set...
    Alkaidx閱讀 607評論 0 0
  • 定時器 JavaScript提供定時執(zhí)行代碼的功能,叫做定時器(timer),主要由setTimeout()和se...
    李諾哦閱讀 1,088評論 0 0

友情鏈接更多精彩內(nèi)容