javascript
理解JS的事件循环过程
眾所周知,JS引擎是單線程的,但是為了實(shí)現(xiàn)異步處理,會(huì)有其他線程來處理異步的事件,本篇來詳細(xì)介紹JS處理異步函數(shù)的過程。首先了解幾個(gè)概念:
宿主環(huán)境:JS運(yùn)行的環(huán)境稱為宿主環(huán)境,需要清楚的是JS不僅可以在瀏覽器上運(yùn)行,也可以在服務(wù)器上運(yùn)行。
執(zhí)行棧(call stack):一個(gè)數(shù)據(jù)結(jié)構(gòu),用于存放各種函數(shù)的執(zhí)行環(huán)境,每一個(gè)函數(shù)執(zhí)行之前,它的相關(guān)信息會(huì)加入到執(zhí)行棧。函數(shù)調(diào)用之前,創(chuàng)建執(zhí)行環(huán)境,然后加入到執(zhí)行棧;函數(shù)調(diào)用之后,銷毀執(zhí)行環(huán)境。
JS引擎執(zhí)行順序:執(zhí)行的是執(zhí)行棧的最頂部
異步函數(shù):某些函數(shù)不會(huì)立即執(zhí)行,需要等到某個(gè)時(shí)機(jī)到達(dá)后才會(huì)執(zhí)行,這樣的函數(shù)稱之為異步函數(shù),例如事件處理函數(shù)。異步函數(shù)的執(zhí)行時(shí)機(jī)受宿主環(huán)境控制。
瀏覽器宿主環(huán)境的5個(gè)線程:
- JS引擎:負(fù)責(zé)執(zhí)行執(zhí)行棧最頂部代碼
- GUI線程:負(fù)責(zé)渲染頁面
- 事件監(jiān)聽線程:負(fù)責(zé)監(jiān)聽各種事件
- 計(jì)時(shí)線程:負(fù)責(zé)計(jì)時(shí)
- 網(wǎng)絡(luò)線程:負(fù)責(zé)網(wǎng)絡(luò)通信
接下來解釋一下JS處理異步函數(shù)的過程:當(dāng)瀏覽器的5個(gè)線程上發(fā)生了某個(gè)事件,如果該線程發(fā)現(xiàn),這個(gè)事件有處理程序,它會(huì)將該處理程序加入一個(gè)叫做事件隊(duì)列的內(nèi)存,當(dāng)JS引擎發(fā)現(xiàn),執(zhí)行棧中已經(jīng)沒有了任何內(nèi)容后,會(huì)將事件隊(duì)列中的第一個(gè)函數(shù)加入到執(zhí)行棧中執(zhí)行。JS引擎對事件的取出執(zhí)行方式,以及與宿主環(huán)境的配合,稱之為事件循環(huán)。
事件隊(duì)列在不同的宿主環(huán)境中有所差異,大部分宿主環(huán)境會(huì)將事件隊(duì)列進(jìn)行細(xì)分,在瀏覽器中,事件隊(duì)列分為兩種:
- 宏任務(wù)(隊(duì)列):macroTask,包括計(jì)時(shí)器結(jié)束的回調(diào),事件回調(diào),http回調(diào)等絕大部分異步函數(shù)
- 微任務(wù)(隊(duì)列):microTask,包括MutationObserver,Promise產(chǎn)生的回調(diào)
【注】當(dāng)執(zhí)行棧清空時(shí),JS引擎首先會(huì)將微任務(wù)中的所有任務(wù)依次執(zhí)行結(jié)束,如果沒有微任務(wù),則執(zhí)行宏任務(wù)
超強(qiáng)干貨來襲 云風(fēng)專訪:近40年碼齡,通宵達(dá)旦的技術(shù)人生總結(jié)
以上是生活随笔為你收集整理的理解JS的事件循环过程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ES6新增数据类型符号(2):共享符号与
- 下一篇: 原生JS封装自己的AJAX