亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JavaScript事件循環(huán)機(jī)制的深入理解

 更新時(shí)間:2025年10月20日 11:07:55   作者:flower_tomb  
JavaScript是一種單線(xiàn)程語(yǔ)言,依賴(lài)于事件循環(huán)機(jī)制,完成對(duì)同步和異步任務(wù)的處理,從而實(shí)現(xiàn)非阻塞并發(fā),這篇文章主要介紹了JavaScript事件循環(huán)機(jī)制的相關(guān)資料,需要的朋友可以參考下

首先,我們要理解JavaScript是一門(mén)單線(xiàn)程的語(yǔ)言。所謂單線(xiàn)程,簡(jiǎn)單來(lái)說(shuō)一個(gè)時(shí)間只能做一件事,只有做完這件事,才能進(jìn)行下一件。那為什么選擇單線(xiàn)程,不選擇多線(xiàn)程呢?這是由JS的用途決定的,JS的用途是與用戶(hù)交互,以及操作DOM,假設(shè)JS有兩個(gè)線(xiàn)程,一個(gè)要在某個(gè)DOM節(jié)點(diǎn)上添加內(nèi)容,一個(gè)要?jiǎng)h除這個(gè)節(jié)點(diǎn),那瀏覽器該以哪個(gè)為準(zhǔn)呢,事情就變得復(fù)雜了。因此,JS在誕生時(shí)就是單線(xiàn)程,以后也不會(huì)改變。

這個(gè)時(shí)候就出現(xiàn)了問(wèn)題,如果一件任務(wù)耗時(shí)太長(zhǎng),就會(huì)阻塞后面的任務(wù)。這樣肯定是不行的,所以,JS設(shè)計(jì)者將任務(wù)分成同步任務(wù)和異步任務(wù)。

同步任務(wù)就是在主線(xiàn)程(調(diào)用棧 Call Stack)中按照書(shū)寫(xiě)順序依次執(zhí)行的任務(wù)。異步任務(wù)就是不阻塞主線(xiàn)程,而是交由其他線(xiàn)程或系統(tǒng)處理(如瀏覽器 或 Node.js ),處理完畢后,將其回調(diào)函數(shù)推入任務(wù)隊(duì)列。等到主線(xiàn)程空了,任務(wù)隊(duì)列中的任務(wù)再根據(jù)FIFO算法被調(diào)度到主線(xiàn)程中執(zhí)行。

事件循環(huán)的工作流程如下:

1.執(zhí)行調(diào)用棧中的所有同步代碼,直到????!緱J呛筮M(jìn)先出結(jié)構(gòu),但是同步代碼入棧后直接執(zhí)行,執(zhí)行完畢彈出,所以順序還是不變的,但如果函數(shù)嵌套,則調(diào)用??赡艽嬖诙鄬雍瘮?shù)上下文,最后進(jìn)入的上下文最先執(zhí)行完,所以最先彈出】
2.檢查任務(wù)隊(duì)列,依次將任務(wù)調(diào)度到調(diào)用棧中執(zhí)行,直到隊(duì)列空。
3.重復(fù)循環(huán)。

只要調(diào)用??樟?,就去任務(wù)隊(duì)列中讀取任務(wù),【用戶(hù)點(diǎn)擊按鈕觸發(fā)函數(shù),函數(shù)就會(huì)被推入調(diào)用棧執(zhí)行】這個(gè)過(guò)程不斷重復(fù)循環(huán),這就是JavaScript的運(yùn)行機(jī)制, 這種機(jī)制就叫做事件循環(huán)機(jī)制

所以有一個(gè)小細(xì)節(jié)就是setTimeout(callback,s)的真正含義并不是在指定的毫秒數(shù)后調(diào)用函數(shù),而是最快s毫秒后調(diào)用函數(shù),因?yàn)樗枰却骶€(xiàn)程空后再被調(diào)用。

但是這里面還有更細(xì)節(jié)的問(wèn)題,在事件循環(huán)的早期設(shè)計(jì)中,所有異步任務(wù)都進(jìn)入同一個(gè)任務(wù)隊(duì)列。但隨著前端復(fù)雜度提升,任務(wù)優(yōu)先級(jí)問(wèn)題顯露出來(lái):

緊急任務(wù)需要優(yōu)先處理(如 Promise 狀態(tài)更新)
非緊急任務(wù)可以延后(如 UI 渲染前的計(jì)算)

因此,現(xiàn)代事件循環(huán)又將異步任務(wù)細(xì)分為兩類(lèi):

同步任務(wù)與宏任務(wù):整個(gè)腳本(主線(xiàn)程代碼),即script標(biāo)簽里的代碼,本身就是一個(gè)宏任務(wù),主線(xiàn)程執(zhí)行腳本中的同步代碼屬于初始宏任務(wù)。整個(gè)腳本的執(zhí)行是第一個(gè)宏任務(wù),同步代碼是它的組成部分。

于是,事件循環(huán)的工作流程就變成:

1.按照代碼書(shū)寫(xiě)順序執(zhí)行初始宏任務(wù):

如果遇到同步代碼,直接推入調(diào)用棧執(zhí)行。
如果遇到宏任務(wù),將回調(diào)函數(shù)推入宏任務(wù)隊(duì)列。
如果遇到微任務(wù),將回調(diào)函數(shù)推入微任務(wù)隊(duì)列。

2.清空微任務(wù)隊(duì)列:

當(dāng)前宏任務(wù)執(zhí)行完畢后,依次將微任務(wù)隊(duì)列中的所有微任務(wù)推入調(diào)用棧執(zhí)行,直到微任務(wù)隊(duì)列清空。
注意:若微任務(wù)中又生成新的微任務(wù),新微任務(wù)也會(huì)在此階段被立即執(zhí)行。

3.渲染更新(如有必要):

瀏覽器判斷是否需要渲染(通常根據(jù)屏幕刷新率,如 60Hz 對(duì)應(yīng)約 16.6ms/次)。

4.開(kāi)啟下一輪事件循環(huán):

從宏任務(wù)隊(duì)列中取出下一個(gè)宏任務(wù)執(zhí)行,重復(fù)上述流程。

Tips:我的一些思路歷程

剛開(kāi)始我以為js在遇到settimeout這種定時(shí)器時(shí),會(huì)將整個(gè)定時(shí)器函數(shù)推到宏任務(wù)隊(duì)列中,但其實(shí)不是的,
【如果是這樣的話(huà),那一個(gè)3秒的宏任務(wù),會(huì)和一個(gè)耗費(fèi)8秒的微任務(wù)幾乎同時(shí)分別推入宏任務(wù)隊(duì)列和微任務(wù)隊(duì)列,那這個(gè)時(shí)候如果調(diào)用棧執(zhí)行空了,先取出這個(gè)微任務(wù)執(zhí)行,那可能8s的打印出來(lái)了,定時(shí)器還沒(méi)打印出來(lái),這個(gè)深究的話(huà)這個(gè)理解是錯(cuò)誤的,不過(guò)可以幫我記住任務(wù)隊(duì)列里放的都是處理過(guò)的回調(diào)

js遇到定時(shí)器之后,將定時(shí)器以及回調(diào)交給瀏覽器,由瀏覽器的定時(shí)模塊發(fā)起定時(shí),處理完畢后(例如三秒后)將回調(diào)函數(shù)推入宏任務(wù)隊(duì)列。

接著列舉一些宏任務(wù)和微任務(wù)的理解,以及他們是怎么分類(lèi)的

宏任務(wù):

由宿主環(huán)境發(fā)起,比如瀏覽器或者Node。js遇到這些任務(wù)時(shí)會(huì)向?qū)?yīng)的環(huán)境發(fā)起請(qǐng)求,由瀏覽器或者node進(jìn)行處理,處理完畢后推入宏任務(wù)隊(duì)列

‌瀏覽器環(huán)境‌: setTimeout、setInterval【定時(shí)器觸發(fā)線(xiàn)程】、DOM事件【事件觸發(fā)線(xiàn)程、GUI渲染線(xiàn)程】、AJAX回調(diào)【瀏覽器網(wǎng)絡(luò)線(xiàn)程】等需要瀏覽器線(xiàn)程協(xié)作的任務(wù)
‌Node環(huán)境‌: I/O操作、setImmediate等系統(tǒng)級(jí)異步操作

微任務(wù):

由JavaScript引擎自身發(fā)起和管理【相當(dāng)于是一種js本身的異步機(jī)制】,例如js遇到promise的時(shí)候,會(huì)執(zhí)行promise的同步部分,然后將promise的狀態(tài)標(biāo)記為pending,而直到當(dāng)resolve/reject被調(diào)用時(shí),js才會(huì)將對(duì)應(yīng)的.then或者.catch回調(diào)函數(shù)推入微任務(wù)隊(duì)列

‌語(yǔ)言級(jí)實(shí)現(xiàn)‌:Promise.then/catch/finally、queueMicrotask等屬于ECMAScript規(guī)范定義的異步機(jī)制

到此這篇關(guān)于JavaScript事件循環(huán)機(jī)制的文章就介紹到這了,更多相關(guān)js事件循環(huán)機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JS跨域代碼片段

    JS跨域代碼片段

    js跨域我用的比較多的就是jsonp和程序代理。但是jsonp只能用get,而且是js異步調(diào)用,有時(shí)候不能滿(mǎn)足項(xiàng)目要求
    2012-08-08
  • bootstrap動(dòng)態(tài)添加面包屑(breadcrumb)及其響應(yīng)事件的方法

    bootstrap動(dòng)態(tài)添加面包屑(breadcrumb)及其響應(yīng)事件的方法

    這篇文章主要介紹了bootstrap動(dòng)態(tài)添加面包屑(breadcrumb)及其響應(yīng)事件的方法,涉及js數(shù)據(jù)傳輸及定義響應(yīng)事件相關(guān)操作技巧,需要的朋友可以參考下
    2017-05-05
  • Javascript?原型與原型鏈深入詳解

    Javascript?原型與原型鏈深入詳解

    這篇文章主要介紹了Javascript原型與原型鏈深入詳解,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下
    2022-07-07
  • JavaScript阻止回車(chē)提交表單的方法

    JavaScript阻止回車(chē)提交表單的方法

    如何防止回車(chē)(enter)鍵提交表單,其實(shí)很簡(jiǎn)單,就一句話(huà)。onkeydown="if(event.keyCode==13)return false;"把這句寫(xiě)在from標(biāo)簽里面就好了
    2015-12-12
  • JS動(dòng)態(tài)給對(duì)象添加屬性和值的實(shí)現(xiàn)方法

    JS動(dòng)態(tài)給對(duì)象添加屬性和值的實(shí)現(xiàn)方法

    下面小編就為大家?guī)?lái)一篇JS動(dòng)態(tài)給對(duì)象添加屬性和值的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-10-10
  • 關(guān)于網(wǎng)頁(yè)中的無(wú)縫滾動(dòng)的js代碼

    關(guān)于網(wǎng)頁(yè)中的無(wú)縫滾動(dòng)的js代碼

    隨便打開(kāi)一個(gè)網(wǎng)頁(yè),基本上都會(huì)看到無(wú)縫滾動(dòng)或者輪播圖,比如淘寶還有360官網(wǎng)的首頁(yè)。那么這些滾動(dòng)效果是怎么實(shí)現(xiàn)的呢?下面小編給大家分享關(guān)于網(wǎng)頁(yè)中的無(wú)縫滾動(dòng)的js代碼,感興趣的朋友一起看下吧
    2016-06-06
  • 前端實(shí)現(xiàn)一鍵截圖從原理到避坑的完整實(shí)戰(zhàn)指南

    前端實(shí)現(xiàn)一鍵截圖從原理到避坑的完整實(shí)戰(zhàn)指南

    在前端開(kāi)發(fā)過(guò)程中,截圖可是個(gè)相當(dāng)重要的環(huán)節(jié),它能幫助我們直觀(guān)地展示頁(yè)面的設(shè)計(jì)效果、交互狀態(tài),還能用于記錄問(wèn)題、進(jìn)行對(duì)比分析等,這篇文章主要介紹了前端實(shí)現(xiàn)一鍵截圖從原理到避坑的相關(guān)資料,需要的朋友可以參考下
    2025-09-09
  • jsjiami.v6解密原理示例分析

    jsjiami.v6解密原理示例分析

    這篇文章主要為大家介紹了jsjiami.v6解密原理示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • css和js實(shí)現(xiàn)彈出登錄居中界面完整代碼

    css和js實(shí)現(xiàn)彈出登錄居中界面完整代碼

    這篇文章主要介紹了css和js實(shí)現(xiàn)彈出登錄居中界面,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2017-11-11
  • 下拉列表select 由左邊框移動(dòng)到右邊示例

    下拉列表select 由左邊框移動(dòng)到右邊示例

    select由左邊框移動(dòng)到右邊,下面有個(gè)不錯(cuò)的示例,大家可以參考下
    2013-12-12

最新評(píng)論