女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

JavaScript定時(shí)器與執(zhí)行機(jī)制介紹

jf_78858299 ? 來(lái)源:前端大全 ? 作者:前端大全 ? 2023-04-21 14:31 ? 次閱讀

從JS執(zhí)行機(jī)制說(shuō)起

瀏覽器(或者說(shuō)JS引擎)執(zhí)行JS的機(jī)制是基于事件循環(huán)。

由于JS是單線程,所以同一時(shí)間只能執(zhí)行一個(gè)任務(wù),其他任務(wù)就得排隊(duì),后續(xù)任務(wù)必須等到前一個(gè)任務(wù)結(jié)束才能開(kāi)始執(zhí)行。

為了避免因?yàn)槟承╅L(zhǎng)時(shí)間任務(wù)造成的無(wú)意義等待,JS引入了異步的概念,用另一個(gè)線程來(lái)管理異步任務(wù)。

同步任務(wù)直接在主線程隊(duì)列中順序執(zhí)行,而異步任務(wù)會(huì)進(jìn)入另一個(gè)任務(wù)隊(duì)列,不會(huì)阻塞主線程。等到主線程隊(duì)列空了(執(zhí)行完了)的時(shí)候,就會(huì)去異步隊(duì)列查詢是否有可執(zhí)行的異步任務(wù)了(異步任務(wù)通常進(jìn)入異步隊(duì)列之后還要等一些條件才能執(zhí)行,如ajax請(qǐng)求、文件讀寫(xiě)),如果某個(gè)異步任務(wù)可以執(zhí)行了便加入主線程隊(duì)列,以此循環(huán)。

JS定時(shí)器

JS的定時(shí)器目前有三個(gè):setTimeout、setInterval和setImmediate。

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

JS定時(shí)器非常實(shí)用,做動(dòng)畫(huà)的肯定都用到過(guò),也是最常用的異步模型之一。

有時(shí)候一些奇奇怪怪的問(wèn)題,加一個(gè)setTimeout(fn, 0)(以下簡(jiǎn)寫(xiě)setTimeout(0))就解決了。不過(guò),如果對(duì)定時(shí)器本身不熟悉,也會(huì)產(chǎn)生一些奇奇怪怪的問(wèn)題。

setTimeout

setTimeout(fn, x)表示延遲x毫秒之后執(zhí)行fn。

使用的時(shí)候千萬(wàn)不要太相信預(yù)期,延遲的時(shí)間嚴(yán)格來(lái)說(shuō)總是大于x毫秒的,至于大多少就要看當(dāng)時(shí)JS的執(zhí)行情況了。

另外,多個(gè)定時(shí)器如不及時(shí)清除(clearTimeout),會(huì)存在干擾,使延遲時(shí)間更加捉摸不透。所以,不管定時(shí)器有沒(méi)有執(zhí)行完,及時(shí)清除已經(jīng)不需要的定時(shí)器是個(gè)好習(xí)慣。

HTML5規(guī)范規(guī)定最小延遲時(shí)間不能小于4ms,即x如果小于4,會(huì)被當(dāng)做4來(lái)處理。 不過(guò)不同瀏覽器的實(shí)現(xiàn)不一樣,比如,Chrome可以設(shè)置1ms,IE11/Edge是4ms。

setTimeout注冊(cè)的函數(shù)fn會(huì)交給瀏覽器的定時(shí)器模塊來(lái)管理,延遲時(shí)間到了就將fn加入主進(jìn)程執(zhí)行隊(duì)列,如果隊(duì)列前面還有沒(méi)有執(zhí)行完的代碼,則又需要花一點(diǎn)時(shí)間等待才能執(zhí)行到fn,所以實(shí)際的延遲時(shí)間會(huì)比設(shè)置的長(zhǎng)。如在fn之前正好有一個(gè)超級(jí)大循環(huán),那延遲時(shí)間就不是一丁點(diǎn)了。

(function testSetTimeout() {

const label = 'setTimeout';

console.time(label);

setTimeout(() => {

    console.timeEnd(label);

}, 10);

for(let i = 0; i < 100000000; i++) {}

})();

結(jié)果是:setTimeout: 335.187ms,遠(yuǎn)遠(yuǎn)不止10ms。

setInterval

setInterval的實(shí)現(xiàn)機(jī)制跟setTimeout類似,只不過(guò)setInterval是重復(fù)執(zhí)行的。

對(duì)于setInterval(fn, 100)容易產(chǎn)生一個(gè)誤區(qū):并不是上一次fn執(zhí)行完了之后再過(guò)100ms才開(kāi)始執(zhí)行下一次fn。 事實(shí)上,setInterval并不管上一次fn的執(zhí)行結(jié)果,而是每隔100ms就將fn放入主線程隊(duì)列,而兩次fn之間具體間隔多久就不一定了,跟setTimeout實(shí)際延遲時(shí)間類似,和JS執(zhí)行情況有關(guān)。

(function testSetInterval() {

let i = 0;

const start = Date.now();

const timer = setInterval(() => {

    i += 1;

    i === 5 && clearInterval(timer);

    console.log(`第${i}次開(kāi)始`, Date.now() - start);

    for(let i = 0; i < 100000000; i++) {}

    console.log(`第${i}次結(jié)束`, Date.now() - start);

}, 100);

})();

輸出

第1次開(kāi)始 100

第1次結(jié)束 1089

第2次開(kāi)始 1091

第2次結(jié)束 1396

第3次開(kāi)始 1396

第3次結(jié)束 1701

第4次開(kāi)始 1701

第4次結(jié)束 2004

第5次開(kāi)始 2004

第5次結(jié)束 2307

可見(jiàn),雖然每次fn執(zhí)行時(shí)間都很長(zhǎng),但下一次并不是等上一次執(zhí)行完了再過(guò)100ms才開(kāi)始執(zhí)行的,實(shí)際上早就已經(jīng)等在隊(duì)列里了。

另外可以看出,當(dāng)setInterval的回調(diào)函數(shù)執(zhí)行時(shí)間超過(guò)了延遲時(shí)間,已經(jīng)完全看不出有時(shí)間間隔了。

如果setTimeout和setInterval都在延遲100ms之后執(zhí)行,那么誰(shuí)先注冊(cè)誰(shuí)就先執(zhí)行回調(diào)函數(shù)。

setImmediate

這算一個(gè)比較新的定時(shí)器,目前IE11/Edge支持、Nodejs支持,Chrome不支持,其他瀏覽器未測(cè)試。

從API名字來(lái)看很容易聯(lián)想到setTimeout(0),不過(guò)setImmediate應(yīng)該算是setTimeout(0)的替代版。

在IE11/Edge中,setImmediate延遲可以在1ms以內(nèi),而setTimeout有最低4ms的延遲,所以setImmediate比setTimeout(0)更早執(zhí)行回調(diào)函數(shù)。不過(guò)在Nodejs中,兩者誰(shuí)先執(zhí)行都有可能,原因是Nodejs的事件循環(huán)和瀏覽器的略有差異。

(function testSetImmediate() {

const label = 'setImmediate';

console.time(label);


setImmediate(() => {

    console.timeEnd(label);

});

})();

Edge輸出:setImmediate: 0.555 毫秒

很明顯,setImmediate設(shè)計(jì)來(lái)是為保證讓代碼在下一次事件循環(huán)執(zhí)行,以前setTimeout(0)這種不可靠的方式可以丟掉了。

其他常用異步模型

requestAnimationFrame

requestAnimationFrame并不是定時(shí)器,但和setTimeout很相似,在沒(méi)有requestAnimationFrame的瀏覽器一般都是用setTimeout模擬

requestAnimationFrame跟屏幕刷新同步,大多數(shù)屏幕的刷新頻率都是60Hz,對(duì)應(yīng)的requestAnimationFrame大概每隔16.7ms觸發(fā)一次,如果屏幕刷新頻率更高,requestAnimationFrame也會(huì)更快觸發(fā)。基于這點(diǎn),在支持requestAnimationFrame的瀏覽器還使用setTimeout做動(dòng)畫(huà)顯然是不明智的。

在不支持requestAnimationFrame的瀏覽器,如果使用setTimeout/setInterval來(lái)做動(dòng)畫(huà),最佳延遲時(shí)間也是16.7ms。 如果太小,很可能連續(xù)兩次或者多次修改dom才一次屏幕刷新,這樣就會(huì)丟幀,動(dòng)畫(huà)就會(huì)卡;如果太大,顯而易見(jiàn)也會(huì)有卡頓的感覺(jué)。

有趣的是,第一次觸發(fā)requestAnimationFrame的時(shí)機(jī)在不同瀏覽器也存在差異,Edge中,大概16.7ms之后觸發(fā),而Chrome則立即觸發(fā),跟setImmediate差不多。按理說(shuō)Edge的實(shí)現(xiàn)似乎更符合常理。

Edge輸出:requestAnimationFrame: 16.66 毫秒

Chrome輸出:requestAnimationFrame: 0.698ms

但相鄰兩次requestAnimationFrame的時(shí)間間隔大概都是16.7ms,這一點(diǎn)是一致的。當(dāng)然也不是絕對(duì)的,如果頁(yè)面本身性能就比較低,相隔的時(shí)間可能會(huì)變大,這就意味著頁(yè)面達(dá)不到60fps。

Promise

Promise是很常用的一種異步模型,如果我們想讓代碼在下一個(gè)事件循環(huán)執(zhí)行,可以選擇使用setTimeout(0)、setImmediate、requestAnimationFrame(Chrome)和Promise。

而且Promise的延遲比setImmediate更低,意味著Promise比setImmediate先執(zhí)行。

function testSetImmediate() {

const label = 'setImmediate';

console.time(label);


setImmediate(() => {

    console.timeEnd(label);

});

}

function testPromise() {

const label = 'Promise';

console.time(label);

new Promise((resolve, reject) => {

    resolve();

}).then(() => {

    console.timeEnd(label);

});

}

testSetImmediate();

testPromise();

Edge輸出:Promise: 0.33 毫秒 setImmediate: 1.66 毫秒

盡管setImmediate的回調(diào)函數(shù)比Promise先注冊(cè),但還是Promise先執(zhí)行。

可以肯定的是,在各JS環(huán)境中,Promise都是最先執(zhí)行的,setTimeout(0)、setImmediate和requestAnimationFrame順序不確定。

process.nextTick

process.nextTick是Nodejs的API,比Promise更早執(zhí)行。

事實(shí)上,process.nextTick是不會(huì)進(jìn)入異步隊(duì)列的,而是直接在主線程隊(duì)列尾強(qiáng)插一個(gè)任務(wù),雖然不會(huì)阻塞主線程,但是會(huì)阻塞異步任務(wù)的執(zhí)行,如果有嵌套的process.nextTick,那異步任務(wù)就永遠(yuǎn)沒(méi)機(jī)會(huì)被執(zhí)行到了。

使用的時(shí)候要格外小心,除非你的代碼明確要在本次事件循環(huán)結(jié)束之前執(zhí)行,否則使用setImmediate或者Promise更保險(xiǎn)。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 定時(shí)器
    +關(guān)注

    關(guān)注

    23

    文章

    3285

    瀏覽量

    117113
  • JS
    JS
    +關(guān)注

    關(guān)注

    0

    文章

    78

    瀏覽量

    18387
  • 循環(huán)
    +關(guān)注

    關(guān)注

    0

    文章

    92

    瀏覽量

    16236
  • 單線程
    +關(guān)注

    關(guān)注

    0

    文章

    18

    瀏覽量

    1821
收藏 人收藏

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    RT-Thread定時(shí)器工作機(jī)制以及定時(shí)器的管理方式

    當(dāng)不再需要?jiǎng)討B(tài)定時(shí)器時(shí),可以將其刪除,執(zhí)行如下函數(shù)之后系統(tǒng)會(huì)把這個(gè)定時(shí)器從 rt_timer_list 鏈表中刪除,然后釋放相應(yīng)的定時(shí)器控制塊占有的內(nèi)存:rt_err_t rt_tim
    的頭像 發(fā)表于 02-15 10:36 ?1.3w次閱讀
    RT-Thread<b class='flag-5'>定時(shí)器</b>工作<b class='flag-5'>機(jī)制</b>以及<b class='flag-5'>定時(shí)器</b>的管理方式

    請(qǐng)問(wèn)軟件定時(shí)器執(zhí)行的回調(diào)函數(shù)是否有優(yōu)先級(jí)機(jī)制

    最近小弟在學(xué)習(xí)UCOSIII系統(tǒng),到了軟件定時(shí)器優(yōu)先級(jí)這一部分,有一個(gè)問(wèn)題一直卡在心里。軟件定時(shí)器到達(dá)后執(zhí)行的回調(diào)函數(shù)有沒(méi)有優(yōu)先級(jí)這種機(jī)制?是不是說(shuō),軟件
    發(fā)表于 05-27 05:51

    555定時(shí)器

    555定時(shí)器555定時(shí)器555定時(shí)器555定時(shí)器555定時(shí)器555定時(shí)器555
    發(fā)表于 11-10 17:25 ?53次下載

    定時(shí)器介紹

    同時(shí)用兩個(gè)定時(shí)器控制蜂鳴器發(fā)聲, 定時(shí)器0控制頻率,定時(shí)器1控制同個(gè) 頻率持續(xù)的時(shí)間,間隔2s依次輸出 1,10,50100,200400800
    發(fā)表于 02-23 15:56 ?20次下載

    STM32定時(shí)器-基本定時(shí)器

    目錄定時(shí)器分類基本定時(shí)器功能框圖講解基本定時(shí)器功能時(shí)鐘源計(jì)數(shù)時(shí)鐘計(jì)數(shù)自動(dòng)重裝載寄存
    發(fā)表于 11-23 18:21 ?32次下載
    STM32<b class='flag-5'>定時(shí)器</b>-基本<b class='flag-5'>定時(shí)器</b>

    STM32定時(shí)器US延時(shí)

    定時(shí)器介紹的SysTick定時(shí)器,該定時(shí)器位于Cortex-M3內(nèi)核中。外設(shè)定時(shí)器由芯片半導(dǎo)體廠商設(shè)計(jì),如STM32系列,包含常規(guī)
    發(fā)表于 12-05 15:36 ?25次下載
    STM32<b class='flag-5'>定時(shí)器</b>US延時(shí)

    軟件定時(shí)器簡(jiǎn)介及程序配置

      軟件定時(shí)器就是允許函數(shù)設(shè)置一定的等待時(shí)間,然后執(zhí)行定時(shí)器執(zhí)行的函數(shù)被稱為定時(shí)器的回調(diào)函數(shù)。定時(shí)器
    的頭像 發(fā)表于 12-06 16:10 ?4328次閱讀
    軟件<b class='flag-5'>定時(shí)器</b>簡(jiǎn)介及程序配置

    STM32定時(shí)器的分類及中斷原理

    本文主要介紹常規(guī)定時(shí)器中的TIM3,實(shí)現(xiàn)定時(shí)器中斷的功能。STM32定時(shí)器的分類在其中一篇文章中已經(jīng)介紹過(guò),本文主要內(nèi)容主要
    的頭像 發(fā)表于 01-12 17:29 ?7950次閱讀
    STM32<b class='flag-5'>定時(shí)器</b>的分類及中斷原理

    555定時(shí)器及應(yīng)用介紹

    555定時(shí)器及應(yīng)用介紹
    的頭像 發(fā)表于 04-12 09:14 ?1878次閱讀

    STM32定時(shí)器介紹

    本文將介紹STM32定時(shí)器的一些基本概念性的東西,方便后面內(nèi)容的理解學(xué)習(xí)。
    的頭像 發(fā)表于 04-21 11:33 ?3512次閱讀
    STM32<b class='flag-5'>定時(shí)器</b><b class='flag-5'>介紹</b>

    簡(jiǎn)述javascript定時(shí)器工作原理

    說(shuō)到 javascript 中的定時(shí)器,我們肯定會(huì)想到 setTimeout() 和 setInterval() 這兩個(gè)函數(shù)。本文將從事件循環(huán)(Event Loop) 的角度來(lái)分析兩者的工作原理和區(qū)別。
    的頭像 發(fā)表于 04-21 14:32 ?1033次閱讀
    簡(jiǎn)述<b class='flag-5'>javascript</b><b class='flag-5'>定時(shí)器</b>工作原理

    定時(shí)器作用及實(shí)現(xiàn)定時(shí)器數(shù)據(jù)結(jié)構(gòu)選取介紹1

    定時(shí)器在各種場(chǎng)景都需要用到,比如游戲的Buff實(shí)現(xiàn),Redis中的過(guò)期任務(wù),Linux中的定時(shí)任務(wù)等等。顧名思義,定時(shí)器的主要用途是執(zhí)行定時(shí)
    的頭像 發(fā)表于 04-21 15:20 ?1442次閱讀
    <b class='flag-5'>定時(shí)器</b>作用及實(shí)現(xiàn)<b class='flag-5'>定時(shí)器</b>數(shù)據(jù)結(jié)構(gòu)選取<b class='flag-5'>介紹</b>1

    定時(shí)器作用及實(shí)現(xiàn)定時(shí)器數(shù)據(jù)結(jié)構(gòu)選取介紹2

    定時(shí)器在各種場(chǎng)景都需要用到,比如游戲的Buff實(shí)現(xiàn),Redis中的過(guò)期任務(wù),Linux中的定時(shí)任務(wù)等等。顧名思義,定時(shí)器的主要用途是執(zhí)行定時(shí)
    的頭像 發(fā)表于 04-21 15:20 ?1369次閱讀
    <b class='flag-5'>定時(shí)器</b>作用及實(shí)現(xiàn)<b class='flag-5'>定時(shí)器</b>數(shù)據(jù)結(jié)構(gòu)選取<b class='flag-5'>介紹</b>2

    高級(jí)定時(shí)器的功能介紹

      本文將介紹高級(jí)定時(shí)器的功能。
    的頭像 發(fā)表于 05-01 09:01 ?3703次閱讀
    高級(jí)<b class='flag-5'>定時(shí)器</b>的功能<b class='flag-5'>介紹</b>

    FreeRTOS的定時(shí)器設(shè)計(jì)實(shí)現(xiàn)

    定時(shí)器用于根據(jù)系統(tǒng)時(shí)啟動(dòng)特定的函數(shù),執(zhí)行相應(yīng)的任務(wù)。FreeRTOS的定時(shí)器可以配置啟動(dòng)一次或者間隔一定時(shí)執(zhí)行
    的頭像 發(fā)表于 07-25 15:28 ?2548次閱讀
    FreeRTOS的<b class='flag-5'>定時(shí)器</b>設(shè)計(jì)實(shí)現(xiàn)