摘要:換個說法微任務(wù)優(yōu)先于當(dāng)前調(diào)用棧產(chǎn)生的宏任務(wù)被執(zhí)行如果能理解下面這段代碼的執(zhí)行過程應(yīng)該就基本理解任務(wù)隊列的執(zhí)行過程了輸出順序為,,,,,,
這篇文章是我自己的一個學(xué)習(xí)總結(jié),并不是非常詳細,結(jié)合給出的鏈接可以有更細致的認識
先介紹幾個概念,便于理解
關(guān)于堆和棧(作為內(nèi)存區(qū)域來說)堆(heap):存放object、array、function等不確定內(nèi)存大小的數(shù)據(jù)存儲;
棧(stack):存放基本數(shù)據(jù)類型以及引用數(shù)據(jù)類型指向堆中的數(shù)據(jù)的指針,具有具體大小的數(shù)據(jù)結(jié)構(gòu),存取速度快;
調(diào)用棧(作為一種代碼運行機制)call stack(調(diào)用棧)指的是函數(shù)調(diào)用運行的機制,具體參考該鏈接:javascrip調(diào)用棧
事件循環(huán)機制(event loop)參考:js事件循環(huán)機制
存在整個javascript腳本執(zhí)行期間
作用:將任務(wù)隊列的中可以執(zhí)行的函數(shù)壓入調(diào)用棧中
任務(wù)隊列(task queue)任務(wù)隊列主要分為兩種:
宏任務(wù)(macro task):在新標(biāo)準(zhǔn)中叫task
宏任務(wù)主要包括:script(整體代碼), setTimeout, setInterval, setImmediate, I/O, UI rendering
微任務(wù)(micro task):在新標(biāo)準(zhǔn)中叫jobs
微任務(wù)主要包括:process.nextTick, Promise, Object.observe(已廢棄), MutationObserver(html5新特性)
以上提到的不只有瀏覽器方法,還有nodejs的方法,這里不具體說明了
執(zhí)行特點:每當(dāng)調(diào)用棧為空時,事件循環(huán)機制會將一個宏任務(wù)隊列中任務(wù)壓入調(diào)用棧中
以空的調(diào)用棧為起點的話,先執(zhí)行所有宏任務(wù),再執(zhí)行所有微任務(wù),然后調(diào)用棧又為空,這樣一次可以看作一個單元,之后就是一直在循環(huán)執(zhí)行這樣單元
分解執(zhí)行過程:
執(zhí)行所有調(diào)用棧中的宏任務(wù)
宏任務(wù)執(zhí)行過程中產(chǎn)生的微任務(wù)加入到微任務(wù)隊列
宏任務(wù)執(zhí)行完立刻執(zhí)行所有微任務(wù)隊列中的任務(wù)
以上執(zhí)行完畢,檢查渲染,GUI線程接管渲染
渲染完畢后,js線程接管,開啟下一次事件循環(huán)(每一次事件循環(huán)(script不包括),只處理一個宏任務(wù)),執(zhí)行下一次宏任務(wù)(任務(wù)隊列中?。?/p>
不好理解的地方:
以上過程(無論宏任務(wù)還是微任務(wù)執(zhí)行)中產(chǎn)生的宏任務(wù)進入宏任務(wù)隊列等待,進入后面的循環(huán)執(zhí)行,不在當(dāng)次循環(huán)中被執(zhí)行
但是以上過程中(包括微任務(wù))產(chǎn)生的微任務(wù)又會被立刻放到當(dāng)次循環(huán)的微任務(wù)隊列后面按順序執(zhí)行
以上兩句可能有點繞,可以參考上面循環(huán)機制的鏈接,有相關(guān)圖解。
換個說法:微任務(wù)優(yōu)先于當(dāng)前調(diào)用棧產(chǎn)生的宏任務(wù)被執(zhí)行
如果能理解下面這段代碼的執(zhí)行過程應(yīng)該就基本理解任務(wù)隊列的執(zhí)行過程了:
setTimeout(() => { console.log("1") new Promise((resolve) => { resolve() }).then(() => { console.log("2") }) }, 0); setTimeout(() => { console.log("3") }, 0); new Promise((resolve) => { resolve() }).then(() => { console.log("4") new Promise((resolve) => { resolve() }).then(() => { console.log("5") }) setTimeout(() => { console.log("6") }, 0); }) new Promise((resolve) => { resolve() }).then(() => { console.log("7") }) // 輸出順序為: 4,7,5,1,2,3,6
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/97486.html
摘要:從異步過程的角度看,函數(shù)就是異步過程的發(fā)起函數(shù),事件監(jiān)聽函數(shù)就是異步過程的回調(diào)函數(shù)。事件觸發(fā)時,表示異步任務(wù)完成,會將事件監(jiān)聽器函數(shù)封裝成一條消息放到消息隊列中,等待主線程執(zhí)行。 1.為什么JavaScript是單線程? JavaScript語言的一大特點就是單線程,也就是說,同一個時間只能做一件事。那么,為什么JavaScript不能有多個線程呢?這樣能提高效率啊。JavaScrip...
摘要:接下來處理微任務(wù)隊列,打印,后面一個不會有任何打印,但是會執(zhí)行執(zhí)行后面的代碼打印進入第二次事件循環(huán),執(zhí)行宏任務(wù)隊列打印 事件循環(huán)機制 理解js的事件循環(huán)機制,能夠很大程度的幫我們更深層次的理解平時遇到的一些很疑惑的問題 簡單版本 下面來看一段代碼,想想它的結(jié)果和你的結(jié)果是否一樣 setTimeout(function() { console.log(1) ...
摘要:異步請求線程在在連接后是通過瀏覽器新開一個線程請求將檢測到狀態(tài)變更時,如果設(shè)置有回調(diào)函數(shù),異步線程就產(chǎn)生狀態(tài)變更事件,將這個回調(diào)再放入事件循環(huán)隊列中。 基礎(chǔ):瀏覽器 -- 多進程,每個tab頁獨立一個瀏覽器渲染進程(瀏覽器內(nèi)核) 每個瀏覽器渲染進程是多線程的,主要包括:GUI渲染線程 JS引擎線程 也稱為JS內(nèi)核,負責(zé)處理Javascript腳本程序。(例如V8引擎) JS引擎線程負...
摘要:的單線程,與它的用途有關(guān)。只要指定過回調(diào)函數(shù),這些事件發(fā)生時就會進入任務(wù)隊列,等待主線程讀取。四主線程從任務(wù)隊列中讀取事件,這個過程是循環(huán)不斷的,所以整個的這種運行機制又稱為事件循環(huán)。令人困惑的是,文檔中稱,指定的回調(diào)函數(shù),總是排在前面。 原文:http://www.cnblogs.com/Master... 一、為什么JavaScript是單線程? JavaScript語言的一大特點...
摘要:而這些隊列由的事件循環(huán)來搞定宏任務(wù)與微任務(wù),在最新標(biāo)準(zhǔn)中,它們被分別稱為與。我們梳理一下事件循環(huán)的執(zhí)行機制循環(huán)首先從宏任務(wù)開始,遇到,生成執(zhí)行上下文,開始進入執(zhí)行棧,可執(zhí)行代碼入棧,依次執(zhí)行代碼,調(diào)用完成出棧。 寫在前面 js是一門單線程的編程語言,也就是說js在處理任務(wù)的時候,所有任務(wù)只能在一個線程上排隊被執(zhí)行,那如果某一個任務(wù)耗時比較長呢?總不能等到它執(zhí)行結(jié)束再去執(zhí)行下一個。所以在...
閱讀 2985·2023-04-26 02:04
閱讀 1293·2021-11-04 16:07
閱讀 3723·2021-09-22 15:09
閱讀 689·2019-08-30 15:54
閱讀 1912·2019-08-29 14:11
閱讀 2539·2019-08-26 12:19
閱讀 2265·2019-08-26 12:00
閱讀 771·2019-08-26 10:27