JS定時(shí)器機(jī)制詳解

前言

JavaScript 提供定時(shí)執(zhí)行代碼的功能队伟,叫做定時(shí)器(timer)速勇,主要由setTimeout()setInterval()這兩個(gè)函數(shù)來(lái)完成敦间。它們向任務(wù)隊(duì)列添加定時(shí)任務(wù)蜓谋。在了解定時(shí)器前区匣,你首頁(yè)也要對(duì)事件循環(huán)機(jī)制有一定的了解偷拔。可以先閱讀這篇文章Js事件循環(huán)(Event Loop)機(jī)制亏钩。

基本概念

什么是定時(shí)器莲绰?

定時(shí)器是一種異步任務(wù),通常瀏覽器都有一個(gè)獨(dú)立的定時(shí)器模塊姑丑,定時(shí)器的延遲時(shí)間就由定時(shí)器模塊來(lái)管理蛤签,當(dāng)某個(gè)定時(shí)器到了可執(zhí)行狀態(tài),就會(huì)被加入主線(xiàn)程隊(duì)列栅哀。

定時(shí)器的運(yùn)行機(jī)制是什么顷啼?

定時(shí)器的運(yùn)行機(jī)制,是將指定的代碼移出本輪事件循環(huán)昌屉,等到下一輪事件循環(huán)钙蒙,再檢查是否到了指定時(shí)間。如果到了间驮,就執(zhí)行對(duì)應(yīng)的代碼躬厌;如果不到,就繼續(xù)等待。

定時(shí)器解決了什么問(wèn)題扛施?

由于JS的單線(xiàn)程特性鸿捧,定時(shí)器提供了一種跳出單線(xiàn)程限制的方法,即讓一段代碼在一定毫秒之后疙渣,再異步執(zhí)行匙奴。

基本用法

setTimeout()

setTimeout函數(shù)用來(lái)指定某個(gè)函數(shù)或某段代碼,在多少毫秒之后執(zhí)行妄荔。它返回一個(gè)整數(shù)泼菌,表示定時(shí)器的編號(hào),以后可以用來(lái)取消這個(gè)定時(shí)器啦租。

var timer = setTimeout(func|code, delay);

clearTimeout(timer);

setTimeout接受兩個(gè)參數(shù):

  • func|code: 是將要推遲執(zhí)行的函數(shù)名或者一段代碼哗伯。
  • delay: 是推遲執(zhí)行的毫秒數(shù)。
  • clearTimeout(): 是取消對(duì)應(yīng)的定時(shí)器的函數(shù)篷角。

除了前兩個(gè)參數(shù)焊刹,setTimeout還允許更多的參數(shù)。它們將依次傳入推遲執(zhí)行的函數(shù)(回調(diào)函數(shù))恳蹲。

舉個(gè)栗子:

setTimeout(function (a,b) {
  console.log(a + b);
}, 1000, 1, 1);

setInterval()

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

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

clearInterval(timer)

上面代碼中贺奠,每隔1000毫秒就輸出一個(gè)2,會(huì)無(wú)限運(yùn)行下去荆针,直到關(guān)閉當(dāng)前窗口敞嗡。clearInterval函數(shù)是用來(lái)取消對(duì)應(yīng)的定時(shí)器的颁糟。其他的跟setTimeout基本一樣航背。

深入機(jī)制

定時(shí)器不是JavaScript的一項(xiàng)功能,而是作為對(duì)象和方法的一部分棱貌,在瀏覽器中使用玖媚。也就是說(shuō),在非瀏覽器環(huán)境中使用JavaScript婚脱,很可能定時(shí)器不存在來(lái)今魔。

我們都知道JavaScript是單線(xiàn)程的,這也決定了在異步事件(鼠標(biāo)單擊障贸、定時(shí)器等)程序的處理中错森,在線(xiàn)程中沒(méi)有代碼的時(shí)候才會(huì)執(zhí)行。即處理程序需要排隊(duì)執(zhí)行篮洁,且不會(huì)被其他處理程序中斷涩维。

下面通過(guò)例子來(lái)了解定時(shí)器的詳細(xì)機(jī)制:

image

  • 0ms時(shí),處啟動(dòng)一個(gè)10ms延遲的定時(shí)器袁波,以及一個(gè)10ms間隔定時(shí)器瓦阐。
  • 6ms時(shí)蜗侈,觸發(fā)鼠標(biāo)點(diǎn)擊事件。
  • 10ms時(shí)睡蟋,定時(shí)器和第一個(gè)間隔定時(shí)器都過(guò)期了(由于主程序還在執(zhí)行踏幻,所以定時(shí)器仍然在排隊(duì),等待空閑在執(zhí)行)戳杀。
  • 由于定時(shí)器和點(diǎn)擊事件都是異步事件该面,所以他們會(huì)進(jìn)行事件排隊(duì),當(dāng)主程序的同步事件執(zhí)行完成(即在18ms之后)豺瘤,線(xiàn)程空閑時(shí)才執(zhí)行吆倦。
  • 18ms時(shí),主線(xiàn)程執(zhí)行完畢坐求,開(kāi)始執(zhí)行隊(duì)列里面的事件蚕泽,隊(duì)列里面現(xiàn)在有鼠標(biāo)單擊事件、setTimeout定時(shí)器和setInterval定時(shí)器桥嗤。
  • 20ms時(shí)须妻,由于隊(duì)列里面有setInterval定時(shí)器,所以第二個(gè)到期的間隔定時(shí)器就會(huì)作廢處理泛领。
  • 28ms時(shí)荒吏,單擊事件執(zhí)行完成,并且在10ms就應(yīng)該執(zhí)行的setTimeout定時(shí)器渊鞋,現(xiàn)在才開(kāi)始執(zhí)行绰更。
  • 30ms時(shí),第三個(gè)setInterval定時(shí)器到期锡宋,因隊(duì)列中有間隔定時(shí)器儡湾,所以第三個(gè)也作廢。
  • 34ms時(shí)执俩,setTimeout定時(shí)器執(zhí)行完成徐钠,開(kāi)始執(zhí)行setInterval,但由于第一個(gè)間隔定時(shí)器在42ms時(shí)結(jié)束役首,所以40ms時(shí)尝丐,到期的第二個(gè)間隔定時(shí)器,又要進(jìn)行排隊(duì)等待衡奥。
  • 47ms時(shí)爹袁,由于第二個(gè)setInterval可以在第三個(gè)間隔定時(shí)器50ms到期時(shí)執(zhí)行完,所以不需要排隊(duì)直接執(zhí)行矮固。

根據(jù)上面的流程進(jìn)行小結(jié):

  • 事件排隊(duì):同時(shí)發(fā)生了這么多事情失息,由于js的單線(xiàn)程特性,當(dāng)線(xiàn)程正在執(zhí)行狀態(tài),有異步事件觸發(fā)時(shí)根时,它就會(huì)排隊(duì)瘦赫,并且在線(xiàn)程空閑時(shí)才進(jìn)行執(zhí)行。并且依照先進(jìn)先出的順序執(zhí)行(先排隊(duì)的先執(zhí)行)蛤迎。
  • setInterval調(diào)用被廢棄:在線(xiàn)程被占用的情況下确虱,并且隊(duì)列中已經(jīng)有setInterval在排隊(duì),則下一個(gè)到期的setInterval會(huì)被廢棄替裆。
  • 定時(shí)器無(wú)法保證準(zhǔn)時(shí)執(zhí)行回調(diào)函數(shù):在主線(xiàn)程還沒(méi)有結(jié)束校辩,即使定時(shí)器時(shí)間到期仍然不會(huì)執(zhí)行,必須等到主程序同步代碼全部執(zhí)行完辆童。
  • setTimeout和setInterval的區(qū)別:其最主要的區(qū)別是功能上的區(qū)別宜咒,setTimeout只延遲執(zhí)行一次,setInterval按時(shí)間周期性的執(zhí)行把鉴。

其他相關(guān)知識(shí):

  • 定時(shí)器不能非常細(xì)凉屎冢化的控制執(zhí)行的時(shí)間,建議在15ms以上庭砍。
  • 可以使用定時(shí)器來(lái)分解長(zhǎng)時(shí)間運(yùn)行的任務(wù)场晶,

結(jié)語(yǔ)

即使設(shè)置了時(shí)間,如果使用不當(dāng)?shù)脑?huà)怠缸,定時(shí)器還是不會(huì)保證準(zhǔn)時(shí)執(zhí)行回調(diào)函數(shù)诗轻。而通過(guò)本文,相信你以前對(duì)定時(shí)器出現(xiàn)過(guò)類(lèi)似問(wèn)題有了一定的了解揭北。希望大家熟練理解原理扳炬,大家加油!搔体!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末恨樟,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子嫉柴,更是在濱河造成了極大的恐慌厌杜,老刑警劉巖奉呛,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件计螺,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡瞧壮,警方通過(guò)查閱死者的電腦和手機(jī)登馒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)咆槽,“玉大人陈轿,你說(shuō)我怎么就攤上這事。” “怎么了麦射?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵蛾娶,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我潜秋,道長(zhǎng)蛔琅,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任峻呛,我火速辦了婚禮罗售,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘钩述。我一直安慰自己寨躁,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布牙勘。 她就那樣靜靜地躺著职恳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪方面。 梳的紋絲不亂的頭發(fā)上话肖,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音葡幸,去河邊找鬼最筒。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蔚叨,可吹牛的內(nèi)容都是我干的床蜘。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼蔑水,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼邢锯!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起搀别,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤丹擎,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后歇父,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蒂培,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年榜苫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了护戳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡垂睬,死狀恐怖媳荒,靈堂內(nèi)的尸體忽然破棺而出抗悍,到底是詐尸還是另有隱情,我是刑警寧澤钳枕,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布缴渊,位于F島的核電站,受9級(jí)特大地震影響鱼炒,放射性物質(zhì)發(fā)生泄漏疟暖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一田柔、第九天 我趴在偏房一處隱蔽的房頂上張望俐巴。 院中可真熱鬧,春花似錦硬爆、人聲如沸欣舵。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)缘圈。三九已至,卻和暖如春袜蚕,著一層夾襖步出監(jiān)牢的瞬間糟把,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工牲剃, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留遣疯,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓凿傅,卻偏偏與公主長(zhǎng)得像缠犀,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子聪舒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容