摘要:事件循環(huán)首先來(lái)看一段代碼運(yùn)行結(jié)果是先輸出,然后大概好幾秒大于一秒以后依次輸出,。原因就在以下這部分代碼中原因就是這部分循環(huán)的代碼執(zhí)行過(guò)程超過(guò)了秒。而這個(gè)循環(huán)是放在里面的。
Event-loop 事件循環(huán)
首先來(lái)看一段代碼
function fn(){ console.log("1") setTimeout(() => { console.log("2") }, 1000) var aa = 0 for (let i = 0; i < 9999999999; i++) { aa = i } if (aa = 9999999998) { console.log("3") } } fn()
運(yùn)行結(jié)果是先輸出1,然后大概好幾秒(大于一秒)以后依次輸出3,2。
setTimeout(() => { console.log("2") }, 1000)
可是上邊這里明明寫了定時(shí)器一秒后輸出字符串2啊,為什么過(guò)了好久才輸出呢?這里就會(huì)引發(fā)思考,js到底是怎么執(zhí)行的
什么是JS事件循環(huán)先來(lái)一張經(jīng)典圖
我們都知道JS是單線程的,所以在它的stack(執(zhí)行棧)里面任務(wù)是排隊(duì)執(zhí)行的,這里我們?cè)诨仡^看開(kāi)始的代碼
function fn(){ console.log("1") setTimeout(() => { console.log("2") }, 1000) var aa = 0 for (let i = 0; i < 9999999999; i++) { aa = i } if (aa = 9999999998) { console.log("3") } } fn()
當(dāng)調(diào)用fn()的時(shí)候,就會(huì)把fn這個(gè)函數(shù)放到stack中去。執(zhí)行步驟分以下幾步
第一步:執(zhí)行console.log("1")第二步:執(zhí)行到setTimeout 的時(shí)候,因?yàn)槲覀兌贾纒etTimeout是異步操作,這里不可能說(shuō)我js停下來(lái)等你1秒,這樣頁(yè)面就卡死在那里了。
這里在回過(guò)頭來(lái)看上面那Event-loop圖
注:js是單線程,但js是運(yùn)行在瀏覽器中的,瀏覽器是多線程的,這一點(diǎn)要搞清楚
當(dāng)我們運(yùn)行到setTimeout這里時(shí),為了不阻塞頁(yè)面,瀏覽器會(huì)在開(kāi)一個(gè)線程來(lái)處理異步的操作,也就是上圖紅框框部分。然后js會(huì)略過(guò)setTimeout,繼續(xù)執(zhí)行下面for循環(huán)的代碼。
當(dāng)一秒鐘之后setTimeout執(zhí)行完畢,就會(huì)將結(jié)果放如到callback queue(回調(diào)隊(duì)列中等待調(diào)用),等待stack中的任務(wù)執(zhí)行完畢后來(lái)調(diào)用它,所以一開(kāi)始fn()函數(shù)的執(zhí)行結(jié)果是1,3,2,、不是1,2,3.就是因?yàn)楫惒降牟僮鞅环旁诹薱allback queue中,等待stack中的執(zhí)行完才會(huì)去找它。
現(xiàn)在我們搞明白了為什么結(jié)果是1,3,2 而不是1,2,3,之后還有一個(gè)問(wèn)題就是為什么setTimeout明明寫的是1秒之后在控制臺(tái)打印出"2"來(lái),為什么實(shí)際體驗(yàn)中要好幾秒之后呢。原因就在以下這部分代碼中
for (let i = 0; i < 9999999999; i++) { aa = i } if (aa = 9999999998) { console.log("3") }
原因就是這部分for循環(huán)的代碼執(zhí)行過(guò)程超過(guò)了1秒。而這個(gè)for循環(huán)是放在stack里面的。它執(zhí)行不完就不會(huì)去callback queue里面找東西,所以我們看到的最終結(jié)果就是
先打印"1"出來(lái)
然后等幾秒后(這個(gè)隨電腦配置不同,時(shí)間長(zhǎng)短不一樣),在打印出"2"
最后才會(huì)打印出"3"
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/109162.html
摘要:檢查宏任務(wù)隊(duì)列,發(fā)現(xiàn)有的回調(diào)函數(shù)立即執(zhí)行回調(diào)函數(shù)輸出。接著遇到它的作用是在后將回調(diào)函數(shù)放到宏任務(wù)隊(duì)列中這個(gè)任務(wù)在再下一次的事件循環(huán)中執(zhí)行。 為什么會(huì)寫這篇博文呢? 前段時(shí)間,和頭條的小伙伴聊天問(wèn)頭條面試前端會(huì)問(wèn)哪些問(wèn)題,他稱如果是他面試的話,event-loop肯定是要問(wèn)的。那天聊了蠻多,event-loop算是給我留下了很深的印象,原因很簡(jiǎn)單,因?yàn)橹拔覐奈瓷钊肓私膺^(guò),如果是面試的時(shí)...
摘要:講的很清晰,看完之后更深一步的理解了事件循環(huán)機(jī)制。簡(jiǎn)短的概述下總結(jié)是一個(gè)宏任務(wù)源,寫在里面的回調(diào)函數(shù)會(huì)加到宏任務(wù)隊(duì)列中。至此,一輪的事件循環(huán)已經(jīng)執(zhí)行完畢,開(kāi)啟新的一輪事件循環(huán)。這就是整段代碼執(zhí)行情況的理解。 這篇文章真的是好文。講的很清晰,看完之后更深一步的理解了事件循環(huán)機(jī)制。 http://www.jianshu.com/p/12b9... 簡(jiǎn)短的概述下總結(jié) setTimeout是一...
摘要:從誕生之日起就是一門單線程的非阻塞的腳本語(yǔ)言。這意味著這些線程實(shí)際上應(yīng)屬于主線程的子線程。所以嚴(yán)格來(lái)講這些線程并沒(méi)有完整的功能,也因此這項(xiàng)技術(shù)并非改變了語(yǔ)言的單線程本質(zhì)。函數(shù)執(zhí)行棧和事件隊(duì)列 瀏覽器渲染 從耗時(shí)的角度,瀏覽器請(qǐng)求、加載、渲染一個(gè)頁(yè)面,時(shí)間花在下面五件事情上:1.DNS 查詢2.TCP 連接3.HTTP 請(qǐng)求即響應(yīng)4.服務(wù)器響應(yīng)5.客戶端渲染 這里重點(diǎn)討論第五個(gè)部分,即瀏...
摘要:所以本來(lái)快輪到你來(lái)辦理業(yè)務(wù),會(huì)因?yàn)槔洗鬆斉R時(shí)添加的理財(cái)業(yè)務(wù)而往后推。在執(zhí)行完同步代碼與微任務(wù)以后,這時(shí)繼續(xù)向后查找有木有宏任務(wù)。所以輸出了第二次,等到這兩次都執(zhí)行完畢后才會(huì)去檢查有沒(méi)有微任務(wù)有沒(méi)有宏任務(wù)。 首先,JavaScript是一個(gè)單線程的腳本語(yǔ)言。 所以就是說(shuō)在一行代碼執(zhí)行的過(guò)程中,必然不會(huì)存在同時(shí)執(zhí)行的另一行代碼,就像使用alert()以后進(jìn)行瘋狂console.log,如...
閱讀 2721·2023-04-26 02:28
閱讀 2551·2021-09-27 13:36
閱讀 3123·2021-09-03 10:29
閱讀 2751·2021-08-26 14:14
閱讀 2101·2019-08-30 15:56
閱讀 830·2019-08-29 13:46
閱讀 2609·2019-08-29 13:15
閱讀 454·2019-08-29 11:29