JS定時(shí)器

在談js定時(shí)器以前,我覺得有必要了解下javascript的事件運(yùn)行機(jī)制绅络,簡稱(javascript event loop)阅悍。眾所周知好渠,javascript是單線程,就是說一次只能完成一個(gè)任務(wù)节视,多個(gè)任務(wù)的執(zhí)行需要排隊(duì)拳锚。前一個(gè)任務(wù)結(jié)束,才能執(zhí)行后一個(gè)任務(wù)寻行,如果前一個(gè)任務(wù)耗時(shí)很長霍掺,后面的任務(wù)就處于掛起狀態(tài),不得不等到前一個(gè)任務(wù)完成拌蜘。

js任務(wù)分為同步和異步任務(wù)杆烁。在了解同步和異步之前,需要理解瀏覽器的并發(fā)模型:



左邊的棧存儲的是同步任務(wù)简卧,所謂同步的任務(wù)就是那些能立即執(zhí)行的任務(wù)兔魂,如變量和初始化、事件綁定等等直接聲明調(diào)用的操作举娩。右邊的堆(heap)用來存儲聲明的對象析校。下面的就是任務(wù)隊(duì)列。一個(gè)某個(gè)異步任務(wù)有了響應(yīng)(觸發(fā))铜涉,就會(huì)被推入隊(duì)列中智玻。如用戶的點(diǎn)擊事件、瀏覽器收到服務(wù)的響應(yīng)和之前提到的setTimeout定時(shí)器事件等等芙代。每個(gè)異步任務(wù)都有一個(gè)回調(diào)函數(shù)吊奢。

再來說說setTimeout:
在單線程的Javascript引擎中,setTimeout()是如何運(yùn)行的呢纹烹,這里就要提到瀏覽器內(nèi)核中的事件循環(huán)模型了页滚。簡單的講,在Javascript執(zhí)行引擎之外铺呵,有一個(gè)任務(wù)隊(duì)列逻谦,當(dāng)在代碼中調(diào)用setTimeout()方法時(shí),注冊的延時(shí)方法會(huì)交由瀏覽器內(nèi)核其他模塊(以webkit為例陪蜻,是webcore模塊)處理,當(dāng)延時(shí)方法到達(dá)觸發(fā)條件贱鼻,即到達(dá)設(shè)置的延時(shí)時(shí)間時(shí)宴卖,這一延時(shí)方法被添加至任務(wù)隊(duì)列里。這一過程由瀏覽器內(nèi)核其他模塊處理邻悬,與執(zhí)行引擎主線程獨(dú)立症昏,執(zhí)行引擎在主線程方法執(zhí)行完畢,到達(dá)空閑狀態(tài)時(shí)父丰,會(huì)從任務(wù)隊(duì)列中順序獲取任務(wù)來執(zhí)行肝谭,這一過程是一個(gè)不斷循環(huán)的過程掘宪,稱為事件循環(huán)模型。

當(dāng)一個(gè)異步事件觸發(fā)攘烛,它的回調(diào)函數(shù)先進(jìn)入事件隊(duì)列中排隊(duì)魏滚,任務(wù)隊(duì)列是一個(gè)先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu),排在前面的事件坟漱,一旦執(zhí)行棧為空鼠次,優(yōu)先被主線程讀取到棧中執(zhí)行。主線程從任務(wù)隊(duì)列中讀取事件芋齿,這個(gè)過程循環(huán)不斷腥寇,所以整個(gè)的這種運(yùn)行機(jī)制又稱為Event loop

下面有必要講下 javascript定時(shí)器的工作原理
有必要看下原文鏈接觅捆,當(dāng)然也能看下袁鍋鍋的Javascript的定時(shí)器的工作原理
為了理解定時(shí)器的內(nèi)部工作原理赦役,我們需要了解一個(gè)非常重要的概念:定時(shí)器設(shè)定的延時(shí)是沒有保證的。因?yàn)樵谒袨g覽器中執(zhí)行的javascript單線程異步事件(比如鼠標(biāo)點(diǎn)擊事件和定時(shí)器)都只有在主線程有空即執(zhí)行棧為空的情況下采取執(zhí)行栅炒。通過圖片來說明:


在解釋上圖時(shí)掂摔,首先先解釋下setTimeout和setInterval的區(qū)別:
setTimeout(fun, delay):延時(shí)delay毫秒之后,啥也不管职辅,直接將回調(diào)函數(shù)推入事件隊(duì)列

setInterval(fun, delay):延時(shí)delay毫秒之后棒呛,先看看事件隊(duì)列中是否存在還沒有執(zhí)行的回調(diào)函數(shù)(setInterval的回調(diào)函數(shù)),如果存在域携,就不需要再往事件隊(duì)列中加入回調(diào)函數(shù)了簇秒。

我們再來解釋上面的圖。
上圖藍(lán)色區(qū)域表示任務(wù)的執(zhí)行時(shí)間秀鞭,首先是Javascript代表的同步任務(wù)趋观。在10ms處注冊了一個(gè)setTimeout事件,并且在之后又多了一個(gè)鼠標(biāo)點(diǎn)擊事件锋边,在鼠標(biāo)點(diǎn)擊事件后又多了個(gè)setInterval事件皱坛。

當(dāng)setTimeout相對注冊該事件過了10ms時(shí),開始觸發(fā)事件豆巨∈1伲可是現(xiàn)在藍(lán)色區(qū)域的同步任務(wù)還未執(zhí)行完,即主線程任務(wù)未執(zhí)行完往扔,執(zhí)行棧還不為空贩猎。則把該處的回調(diào)函數(shù)推入事件隊(duì)列。然而萍膛,事件隊(duì)列中已經(jīng)有一個(gè)點(diǎn)擊觸發(fā)的事件吭服,因?yàn)樗榷〞r(shí)器過10秒才觸發(fā)快,所以優(yōu)先進(jìn)入到隊(duì)列蝗罗。
等Javascript代表的藍(lán)色區(qū)域同步任務(wù)執(zhí)行完之后艇棕,主線程便從任務(wù)隊(duì)列中取到讀到鼠標(biāo)點(diǎn)擊事件蝌戒,開始執(zhí)行mouse click callback的藍(lán)色區(qū)域的回調(diào)函數(shù),然而在這個(gè)區(qū)域中setInterval的離注冊事件過10ms到時(shí)事件開始觸發(fā)沼琉,并將回調(diào)函數(shù)推入事件隊(duì)列中北苟。此時(shí)它的前面排著10ms setTimeout事件。等Mouse Click回調(diào)函數(shù)執(zhí)行完刺桃,執(zhí)行棧又為空粹淋,推入10ms setTimeout事件,并執(zhí)行瑟慈,此時(shí)在Timer藍(lán)色區(qū)域下一個(gè)10ms setInterval事件觸發(fā)桃移,由于之前事件隊(duì)列中有一個(gè)interval事件了,則丟棄葛碧,不進(jìn)入隊(duì)列借杰。
等Timer的回調(diào)執(zhí)行完,隨即執(zhí)行事件隊(duì)列里的第一個(gè)Interval事件进泼,在Interval藍(lán)色執(zhí)行期間蔗衡,又有個(gè)interval事件觸發(fā),則推入事件隊(duì)列乳绕,即本次Interval事件執(zhí)行完下一個(gè)直接取到執(zhí)行棧執(zhí)行绞惦,下面的setInterval事件可謂是暢通無阻了,按照每10ms執(zhí)行~

表達(dá)的不清楚洋措,請見諒济蝉,本文也是結(jié)合了幾篇講解定時(shí)器文章做了一個(gè)總結(jié)。

參考鏈接:
javascript計(jì)時(shí)器工作原理
javascript定時(shí)器工作原理
javascript單線程異步機(jī)制
阮一峰:再談event loop

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末菠发,一起剝皮案震驚了整個(gè)濱河市王滤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌滓鸠,老刑警劉巖雁乡,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異糜俗,居然都是意外死亡踱稍,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門悠抹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來珠月,“玉大人,你說我怎么就攤上這事锌钮。” “怎么了引矩?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵梁丘,是天一觀的道長侵浸。 經(jīng)常有香客問我,道長氛谜,這世上最難降的妖魔是什么掏觉? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮值漫,結(jié)果婚禮上澳腹,老公的妹妹穿的比我還像新娘。我一直安慰自己杨何,他們只是感情好酱塔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著危虱,像睡著了一般羊娃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上埃跷,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天蕊玷,我揣著相機(jī)與錄音,去河邊找鬼弥雹。 笑死垃帅,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的剪勿。 我是一名探鬼主播贸诚,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼窗宦!你這毒婦竟也來了赦颇?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤赴涵,失蹤者是張志新(化名)和其女友劉穎媒怯,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體髓窜,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡扇苞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了寄纵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鳖敷。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖程拭,靈堂內(nèi)的尸體忽然破棺而出定踱,到底是詐尸還是另有隱情,我是刑警寧澤恃鞋,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布崖媚,位于F島的核電站亦歉,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏畅哑。R本人自食惡果不足惜肴楷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望荠呐。 院中可真熱鬧赛蔫,春花似錦、人聲如沸泥张。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽圾结。三九已至瑰剃,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間筝野,已是汗流浹背晌姚。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留歇竟,地道東北人挥唠。 一個(gè)月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像焕议,于是被迫代替她去往敵國和親宝磨。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

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