色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

JavaScript定時器與執行機制介紹

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

從JS執行機制說起

瀏覽器(或者說JS引擎)執行JS的機制是基于事件循環。

由于JS是單線程,所以同一時間只能執行一個任務,其他任務就得排隊,后續任務必須等到前一個任務結束才能開始執行。

為了避免因為某些長時間任務造成的無意義等待,JS引入了異步的概念,用另一個線程來管理異步任務。

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

JS定時器

JS的定時器目前有三個:setTimeout、setInterval和setImmediate。

定時器也是一種異步任務,通常瀏覽器都有一個獨立的定時器模塊,定時器的延遲時間就由定時器模塊來管理,當某個定時器到了可執行狀態,就會被加入主線程隊列。

JS定時器非常實用,做動畫的肯定都用到過,也是最常用的異步模型之一。

有時候一些奇奇怪怪的問題,加一個setTimeout(fn, 0)(以下簡寫setTimeout(0))就解決了。不過,如果對定時器本身不熟悉,也會產生一些奇奇怪怪的問題。

setTimeout

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

使用的時候千萬不要太相信預期,延遲的時間嚴格來說總是大于x毫秒的,至于大多少就要看當時JS的執行情況了。

另外,多個定時器如不及時清除(clearTimeout),會存在干擾,使延遲時間更加捉摸不透。所以,不管定時器有沒有執行完,及時清除已經不需要的定時器是個好習慣。

HTML5規范規定最小延遲時間不能小于4ms,即x如果小于4,會被當做4來處理。 不過不同瀏覽器的實現不一樣,比如,Chrome可以設置1ms,IE11/Edge是4ms。

setTimeout注冊的函數fn會交給瀏覽器的定時器模塊來管理,延遲時間到了就將fn加入主進程執行隊列,如果隊列前面還有沒有執行完的代碼,則又需要花一點時間等待才能執行到fn,所以實際的延遲時間會比設置的長。如在fn之前正好有一個超級大循環,那延遲時間就不是一丁點了。

(function testSetTimeout() {

const label = 'setTimeout';

console.time(label);

setTimeout(() => {

    console.timeEnd(label);

}, 10);

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

})();

結果是:setTimeout: 335.187ms,遠遠不止10ms。

setInterval

setInterval的實現機制跟setTimeout類似,只不過setInterval是重復執行的。

對于setInterval(fn, 100)容易產生一個誤區:并不是上一次fn執行完了之后再過100ms才開始執行下一次fn。 事實上,setInterval并不管上一次fn的執行結果,而是每隔100ms就將fn放入主線程隊列,而兩次fn之間具體間隔多久就不一定了,跟setTimeout實際延遲時間類似,和JS執行情況有關。

(function testSetInterval() {

let i = 0;

const start = Date.now();

const timer = setInterval(() => {

    i += 1;

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

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

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

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

}, 100);

})();

輸出

第1次開始 100

第1次結束 1089

第2次開始 1091

第2次結束 1396

第3次開始 1396

第3次結束 1701

第4次開始 1701

第4次結束 2004

第5次開始 2004

第5次結束 2307

可見,雖然每次fn執行時間都很長,但下一次并不是等上一次執行完了再過100ms才開始執行的,實際上早就已經等在隊列里了。

另外可以看出,當setInterval的回調函數執行時間超過了延遲時間,已經完全看不出有時間間隔了。

如果setTimeout和setInterval都在延遲100ms之后執行,那么誰先注冊誰就先執行回調函數。

setImmediate

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

從API名字來看很容易聯想到setTimeout(0),不過setImmediate應該算是setTimeout(0)的替代版。

在IE11/Edge中,setImmediate延遲可以在1ms以內,而setTimeout有最低4ms的延遲,所以setImmediate比setTimeout(0)更早執行回調函數。不過在Nodejs中,兩者誰先執行都有可能,原因是Nodejs的事件循環和瀏覽器的略有差異。

(function testSetImmediate() {

const label = 'setImmediate';

console.time(label);


setImmediate(() => {

    console.timeEnd(label);

});

})();

Edge輸出:setImmediate: 0.555 毫秒

很明顯,setImmediate設計來是為保證讓代碼在下一次事件循環執行,以前setTimeout(0)這種不可靠的方式可以丟掉了。

其他常用異步模型

requestAnimationFrame

requestAnimationFrame并不是定時器,但和setTimeout很相似,在沒有requestAnimationFrame的瀏覽器一般都是用setTimeout模擬

requestAnimationFrame跟屏幕刷新同步,大多數屏幕的刷新頻率都是60Hz,對應的requestAnimationFrame大概每隔16.7ms觸發一次,如果屏幕刷新頻率更高,requestAnimationFrame也會更快觸發。基于這點,在支持requestAnimationFrame的瀏覽器還使用setTimeout做動畫顯然是不明智的。

在不支持requestAnimationFrame的瀏覽器,如果使用setTimeout/setInterval來做動畫,最佳延遲時間也是16.7ms。 如果太小,很可能連續兩次或者多次修改dom才一次屏幕刷新,這樣就會丟幀,動畫就會卡;如果太大,顯而易見也會有卡頓的感覺。

有趣的是,第一次觸發requestAnimationFrame的時機在不同瀏覽器也存在差異,Edge中,大概16.7ms之后觸發,而Chrome則立即觸發,跟setImmediate差不多。按理說Edge的實現似乎更符合常理。

Edge輸出:requestAnimationFrame: 16.66 毫秒

Chrome輸出:requestAnimationFrame: 0.698ms

但相鄰兩次requestAnimationFrame的時間間隔大概都是16.7ms,這一點是一致的。當然也不是絕對的,如果頁面本身性能就比較低,相隔的時間可能會變大,這就意味著頁面達不到60fps。

Promise

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

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

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的回調函數比Promise先注冊,但還是Promise先執行。

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

process.nextTick

process.nextTick是Nodejs的API,比Promise更早執行。

事實上,process.nextTick是不會進入異步隊列的,而是直接在主線程隊列尾強插一個任務,雖然不會阻塞主線程,但是會阻塞異步任務的執行,如果有嵌套的process.nextTick,那異步任務就永遠沒機會被執行到了。

使用的時候要格外小心,除非你的代碼明確要在本次事件循環結束之前執行,否則使用setImmediate或者Promise更保險。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 定時器
    +關注

    關注

    23

    文章

    3246

    瀏覽量

    114726
  • JS
    JS
    +關注

    關注

    0

    文章

    78

    瀏覽量

    18096
  • 循環
    +關注

    關注

    0

    文章

    92

    瀏覽量

    15973
  • 單線程
    +關注

    關注

    0

    文章

    17

    瀏覽量

    1771
收藏 人收藏

    評論

    相關推薦

    RT-Thread定時器工作機制以及定時器的管理方式

    當不再需要動態定時器時,可以將其刪除,執行如下函數之后系統會把這個定時器從 rt_timer_list 鏈表中刪除,然后釋放相應的定時器控制塊占有的內存:rt_err_t rt_tim
    的頭像 發表于 02-15 10:36 ?1.2w次閱讀
    RT-Thread<b class='flag-5'>定時器</b>工作<b class='flag-5'>機制</b>以及<b class='flag-5'>定時器</b>的管理方式

    請問軟件定時器執行的回調函數是否有優先級機制

    最近小弟在學習UCOSIII系統,到了軟件定時器優先級這一部分,有一個問題一直卡在心里。軟件定時器到達后執行的回調函數有沒有優先級這種機制?是不是說,軟件
    發表于 05-27 05:51

    555定時器

    555定時器555定時器555定時器555定時器555定時器555定時器555
    發表于 11-10 17:25 ?52次下載

    定時器介紹

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

    STM32定時器-基本定時器

    目錄定時器分類基本定時器功能框圖講解基本定時器功能時鐘源計數時鐘計數自動重裝載寄存
    發表于 11-23 18:21 ?31次下載
    STM32<b class='flag-5'>定時器</b>-基本<b class='flag-5'>定時器</b>

    STM32定時器US延時

    定時器介紹的SysTick定時器,該定時器位于Cortex-M3內核中。外設定時器由芯片半導體廠商設計,如STM32系列,包含常規
    發表于 12-05 15:36 ?25次下載
    STM32<b class='flag-5'>定時器</b>US延時

    軟件定時器簡介及程序配置

      軟件定時器就是允許函數設置一定的等待時間,然后執行定時器執行的函數被稱為定時器的回調函數。定時器
    的頭像 發表于 12-06 16:10 ?3899次閱讀
    軟件<b class='flag-5'>定時器</b>簡介及程序配置

    STM32定時器的分類及中斷原理

    本文主要介紹常規定時器中的TIM3,實現定時器中斷的功能。STM32定時器的分類在其中一篇文章中已經介紹過,本文主要內容主要
    的頭像 發表于 01-12 17:29 ?7279次閱讀
    STM32<b class='flag-5'>定時器</b>的分類及中斷原理

    555定時器及應用介紹

    555定時器及應用介紹
    的頭像 發表于 04-12 09:14 ?1609次閱讀

    STM32定時器介紹

    本文將介紹STM32定時器的一些基本概念性的東西,方便后面內容的理解學習。
    的頭像 發表于 04-21 11:33 ?3087次閱讀
    STM32<b class='flag-5'>定時器</b><b class='flag-5'>介紹</b>

    簡述javascript定時器工作原理

    說到 javascript 中的定時器,我們肯定會想到 setTimeout() 和 setInterval() 這兩個函數。本文將從事件循環(Event Loop) 的角度來分析兩者的工作原理和區別。
    的頭像 發表于 04-21 14:32 ?793次閱讀
    簡述<b class='flag-5'>javascript</b><b class='flag-5'>定時器</b>工作原理

    定時器作用及實現定時器數據結構選取介紹1

    定時器在各種場景都需要用到,比如游戲的Buff實現,Redis中的過期任務,Linux中的定時任務等等。顧名思義,定時器的主要用途是執行定時
    的頭像 發表于 04-21 15:20 ?1192次閱讀
    <b class='flag-5'>定時器</b>作用及實現<b class='flag-5'>定時器</b>數據結構選取<b class='flag-5'>介紹</b>1

    定時器作用及實現定時器數據結構選取介紹2

    定時器在各種場景都需要用到,比如游戲的Buff實現,Redis中的過期任務,Linux中的定時任務等等。顧名思義,定時器的主要用途是執行定時
    的頭像 發表于 04-21 15:20 ?1187次閱讀
    <b class='flag-5'>定時器</b>作用及實現<b class='flag-5'>定時器</b>數據結構選取<b class='flag-5'>介紹</b>2

    高級定時器的功能介紹

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

    FreeRTOS的定時器設計實現

    定時器用于根據系統時啟動特定的函數,執行相應的任務。FreeRTOS的定時器可以配置啟動一次或者間隔一定時執行
    的頭像 發表于 07-25 15:28 ?2004次閱讀
    FreeRTOS的<b class='flag-5'>定時器</b>設計實現
    主站蜘蛛池模板: 暖暖视频免费观看视频| 新影音先锋男人色资源网| 国产精品久久婷婷五月色| 91夫妻交友论坛| 亚洲视频无码中字在线| 日韩美女爱爱| 哪灬你的鸣巴好大| 久久亚洲欧美国产综合| 国产AV精品久久久免费看| 做你的爱人BD日本| 亚洲午夜久久久精品影院| 鞋奴的视频VK| 性女传奇 快播| 我的漂亮朋友在线观看全集免费| 欧美高清一区二区三| 嫩草影院未满十八岁禁止入内| 精品国产影院| 久久成人国产精品一区二区| 国产午夜在线视频| 国产香蕉视频在线观看| 国产自产第一区c国产| 国产在线观看成人免费视频| 黑吊大战白女出浆| 精品国产麻豆AV无码| 久久人妻少妇嫩草AV蜜桃99| 久久久精品成人免费看| 捆绑调教网站| 日本边添边摸边做边爱边| 色婷婷五月综合久久中文字幕| 日日碰狠狠添天天爽| 神马电影dy888午夜我不卡| 特黄大片aaaaa毛片| 亚洲AV久久久噜噜噜噜| 亚洲视频在线观看网站| 最好看中文字幕国语| 朝鲜美女bbwbbw撒尿| 国产精品青青草原app大全| 交换娇妻呻吟声不停中文字幕| 老色哥网站| 四房播播开心五月| 印度12 13free|