JS的執(zhí)行機(jī)制(EventLoop、宏任務(wù)和微任務(wù))
1、EventLoop
1. JavaScript 是單線程的語(yǔ)言
JavaScript 是一門(mén)單線程執(zhí)行的編程語(yǔ)言。
也就是說(shuō),同一時(shí)間只能做一件事情。
單線程執(zhí)行任務(wù)隊(duì)列的問(wèn)題:
如果前一個(gè)任務(wù)非常耗時(shí),則后續(xù)的任務(wù)就不得不一直等待,從而導(dǎo)致程序假死的問(wèn)題。
2. 同步任務(wù)和異步任務(wù)
為了防止某個(gè)耗時(shí)任務(wù)導(dǎo)致程序假死的問(wèn)題,JavaScript 把待執(zhí)行的任務(wù)分為了兩類(lèi):
① 同步任務(wù)(synchronous)
又叫做非耗時(shí)任務(wù),指的是在主線程上排隊(duì)執(zhí)行的那些任務(wù)只有前一個(gè)任務(wù)執(zhí)行完畢, 才能執(zhí)行后一個(gè)任務(wù)
② 異步任務(wù)(asynchronous)
又叫做耗時(shí)任務(wù),異步任務(wù)由 JavaScript 委托給 宿主環(huán)境進(jìn)行執(zhí)行當(dāng)異步任務(wù)執(zhí)行完成后,會(huì)通知 JavaScript 主線程執(zhí)行異步任務(wù)的回調(diào)函 數(shù)
3. 同步任務(wù)和異步任務(wù)的執(zhí)行過(guò)程
① 同步任務(wù)由 JavaScript 主線程次序執(zhí)行
② 異步任務(wù)委托給宿主環(huán)境執(zhí)行
③ 已完成的異步任務(wù)對(duì)應(yīng)的回調(diào)函數(shù),會(huì)被加入到任務(wù)隊(duì)列中等待執(zhí)行
④ JavaScript 主線程的執(zhí)行棧被清空后,會(huì) 讀取任務(wù)隊(duì)列中的回調(diào)函數(shù),次序執(zhí)行
⑤ JavaScript 主線程不斷重復(fù)上面的第 4 步
4. EventLoop 的基本概念
JavaScript 主線程從“任務(wù)隊(duì)列”中讀取異步
任務(wù)的回調(diào)函數(shù),放到執(zhí)行棧中依次執(zhí)行。這 個(gè)過(guò)程是循環(huán)不斷的,所以整個(gè)的這種運(yùn)行機(jī) 制又稱(chēng)為EventLoop(事件循環(huán))。
5. 結(jié)合 EventLoop 分析輸出的順序
正確的輸出結(jié)果:ADCB。
其中:
A和D屬于同步任務(wù) 。
會(huì)根據(jù)代碼的先后順序依次被執(zhí)行C和B屬于異步任務(wù)。
它們的回調(diào)函數(shù)會(huì)被加入到任務(wù)隊(duì)列中,等待主線程空閑時(shí)再執(zhí)行
2、宏任務(wù)和微任務(wù)
1.什么是宏任務(wù)和微任務(wù)
JavaScript 把異步任務(wù)又做了進(jìn)一步的劃分,異步任務(wù)又分為兩類(lèi),分別是:
① 宏任務(wù)(macrotask)
異 步 Ajax 請(qǐng)求、 setTimeout 、 setInterval 、 文件操作 其它宏任務(wù)
② 微任務(wù)(microtask)
Promise.then 、 .catch 和 .finally process.nextTick 其它微任務(wù)
2. 宏任務(wù)和微任務(wù)的執(zhí)行順序
每一個(gè)宏任務(wù)執(zhí)行完之后,都會(huì)檢查是否存在待執(zhí)行的微任務(wù),
如果有,則執(zhí)行完所有微任務(wù)之后,再繼續(xù)執(zhí)行下一個(gè)宏任務(wù)。
3. 去銀行辦業(yè)務(wù)的場(chǎng)景(舉例)
① 小云和小騰去銀行辦業(yè)務(wù)。首先,需要取號(hào)之后進(jìn)行排隊(duì)
宏任務(wù)隊(duì)列
② 假設(shè)當(dāng)前銀行網(wǎng)點(diǎn)只有一個(gè)柜員,小云在辦理存款業(yè)務(wù)時(shí),小騰只能等待
單線 程 ,宏任 務(wù) 按次 序 執(zhí)行
③ 小云辦完存款業(yè)務(wù)后,柜員詢(xún)問(wèn)他是否還想辦理其它業(yè)務(wù)?
當(dāng)前宏任務(wù)執(zhí)行完 , 檢 查是 否 有微 任 務(wù)
④ 小云告訴柜員:想要買(mǎi)理財(cái)產(chǎn)品、再辦個(gè)信用卡、最后再兌換點(diǎn)馬年紀(jì)念幣?
執(zhí)行微任務(wù),后 續(xù) 宏 任 務(wù)被 推 遲
⑤ 小云離開(kāi)柜臺(tái)后,柜員開(kāi)始為小騰辦理業(yè)務(wù)
所有微任務(wù)執(zhí)行完 畢 , 開(kāi) 始 執(zhí) 行下 一 個(gè) 宏 任務(wù)
4. 分析以下代碼輸出的順序
正確的輸出順序是:2431
分析:
① 先執(zhí)行所有的同步任務(wù)
執(zhí)行第 6 行、第 12 行代碼
② 再執(zhí)行微任務(wù)
執(zhí)行第 9 行代碼
③ 再執(zhí)行下一個(gè)宏任務(wù)
執(zhí)行 第 2 行代碼
5. 經(jīng)典面試題
請(qǐng)分析以下代碼輸出的順序(代碼較長(zhǎng),截取成了左中右 3 個(gè)部分) :
正確的輸出順序是:156234789
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
cypress e2e測(cè)試編寫(xiě)注意點(diǎn)總結(jié)分析
這篇文章主要為大家介紹了cypress e2e測(cè)試編寫(xiě)注意點(diǎn)總結(jié)分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04JavaScript中關(guān)于遞歸與回溯的實(shí)例詳解
這篇文章主要將為大家介紹一下JavaScript中遞歸與回溯的原理及使用,文中通過(guò)一些例題進(jìn)行了詳細(xì)介紹,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-07-07Markdown與Bootstrap相結(jié)合實(shí)現(xiàn)圖片自適應(yīng)屬性
Markdown 是一種輕量級(jí)的標(biāo)記語(yǔ)言,它的優(yōu)點(diǎn)很多,目前也被越來(lái)越多的寫(xiě)作愛(ài)好者,撰稿者廣泛使用。接下來(lái)通過(guò)本文給大家介紹Markdown與Bootstrap相結(jié)合實(shí)現(xiàn)圖片自適應(yīng)屬性,感興趣的朋友一起學(xué)習(xí)吧2016-05-05JS樹(shù)形菜單組件Bootstrap TreeView使用方法詳解
這篇文章主要為大家詳細(xì)介紹了js組件Bootstrap TreeView使用方法,本文一部分針對(duì)于bootstrap的treeview的實(shí)踐,另一部分是介紹自己寫(xiě)的樹(shù)形菜單,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12JS實(shí)現(xiàn)發(fā)送短信驗(yàn)證后按鈕倒計(jì)時(shí)功能(防止刷新倒計(jì)時(shí)失效)
這篇文章主要介紹了JS實(shí)現(xiàn)發(fā)送短信驗(yàn)證后按鈕倒計(jì)時(shí)功能防止刷新倒計(jì)時(shí)失效問(wèn)題,在項(xiàng)目開(kāi)發(fā)中經(jīng)常會(huì)用到此功能,下面小編通過(guò)本文給大家分享JS實(shí)現(xiàn)發(fā)送短信驗(yàn)證后按鈕倒計(jì)時(shí)功能(防止刷新倒計(jì)時(shí)失效),需要的朋友參考下吧2017-07-07微信小程序pinker組件使用實(shí)現(xiàn)自動(dòng)相減日期
這篇文章主要介紹了微信小程序pinker組件使用實(shí)現(xiàn)自動(dòng)相減日期,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05JS動(dòng)態(tài)添加與刪除select中的Option對(duì)象(示例代碼)
本篇文章主要介紹了JS動(dòng)態(tài)添加與刪除select中的Option對(duì)象示例代碼。需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-12-12