js在瀏覽器中的event loop事件隊列示例詳解
前言
以下內(nèi)容是js在瀏覽器中的事件隊列執(zhí)行,與在nodejs中有所區(qū)別,請注意。
都說js是單線程的,不過它本身其實不是單線程,但是在瀏覽器中執(zhí)行時只分配一個線程進行執(zhí)行。
所以說js執(zhí)行是單線程的,一次只能進行一項任務(wù),就是一件任務(wù)一件任務(wù)做,做完一件做下一件。
認識一個棧兩個隊列
一個調(diào)用棧Stack。
一個宏隊列,macrotask,也叫tasks。
一個微隊列,microtask,也叫jobs。
執(zhí)行過程
js就是執(zhí)行全局Script同步代碼,這中間碰到一些異步任務(wù)先加進對應(yīng)的隊列。
做完之后,調(diào)用棧就為空了。
然后將隊列(先微隊列后宏隊列)里面的首個任務(wù)提到調(diào)用棧來做,一件一件做完直到隊列中的任務(wù)都做完。
總結(jié)就是,先做同步的任務(wù),再做微隊列的任務(wù),再做宏隊列的任務(wù)。
異步任務(wù)怎么分配
這些異步任務(wù)包括但不限于:
以下分配給宏隊列:
setTimeout
setInterval
requestAnimationFrame
I/O
UI rendering
以下分配給微隊列:
Promise
Object.observe
MutationObserver
常見的宏隊列:setTimeout,常見的微隊列:Promise。
簡單例子
console.log("同步任務(wù)1");
setTimeout(() => {
console.log("宏任務(wù)");
});
new Promise((resolve, reject) => {
console.log("同步任務(wù)2");
resolve("微任務(wù)");
}).then((data) => {
console.log(data);
});
console.log("同步任務(wù)3");
結(jié)果是(按標號加任務(wù),按箭頭執(zhí)行):


需要注意的是Promise的第一層沒有執(zhí)行回調(diào)之前是同步的,也就是上面的同步任務(wù)2。
難一點的例子
console.log("同步任務(wù)1");
console.log("同步任務(wù)2");
new Promise((resolve, reject) => {
console.log("同步任務(wù)3");
setTimeout(() => {
console.log("宏任務(wù)1");
Promise.resolve()
.then(() => {
console.log("微任務(wù)5");
})
.then(() => {
console.log("微任務(wù)6");
});
});
resolve("微任務(wù)1");
})
.then((data) => {
console.log(data);
return "微任務(wù)3";
})
.then((data) => {
console.log(data);
});
setTimeout(() => {
console.log("宏任務(wù)2");
}, 0);
new Promise((resolve, reject) => {
resolve("微任務(wù)2");
})
.then((data, resolve) => {
console.log(data);
return "微任務(wù)4";
})
.then((data) => {
console.log(data);
});
console.log("同步任務(wù)4");
如何看呢,先看第一層,紅色代表同步,綠色微任務(wù),藍色宏任務(wù)。
我們會把同步任務(wù)執(zhí)行完,然后看見微任務(wù)有倆,宏任務(wù)也有倆。
本來的執(zhí)行順序可能是這樣(我這里按照序號來表達順序了,請和簡單例子區(qū)分開來):

但是沒那么順利,執(zhí)行到標號6時不一樣了。
因為微任務(wù)執(zhí)行過程中可能會產(chǎn)生新的微任務(wù)。
上面的微任務(wù)1執(zhí)行完會把微任務(wù)3加在微任務(wù)2后面,也就是微任務(wù)2執(zhí)行完也輪不到宏任務(wù),會繼續(xù)執(zhí)行新的微任務(wù)直到微任務(wù)隊列暫時為空。
所以接下來會按照加入隊列的順序執(zhí)行完四個微任務(wù),這時候發(fā)現(xiàn)沒有新的微任務(wù)產(chǎn)生,才開始執(zhí)行宏任務(wù):

但是需要注意的是,上面執(zhí)行到標號5時又不一樣了,宏任務(wù)一執(zhí)行后又產(chǎn)生了新的微任務(wù),所以宏任務(wù)兩個并沒有順利連續(xù)執(zhí)行,而是被插入的微任務(wù)攔住了。
(要記住微任務(wù)與宏任務(wù)隊列都存在時一定是微任務(wù)先執(zhí)行完再來執(zhí)行宏任務(wù),即使是宏任務(wù)執(zhí)行產(chǎn)生的微任務(wù)也同理)

所以最后的答案,如果存在不理解的,可以在認真回顧一下上文:

總結(jié)
到此這篇關(guān)于js在瀏覽器中的event loop事件隊列的文章就介紹到這了,更多相關(guān)js event loop事件隊列內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript中異步與回調(diào)的基本概念及回調(diào)地獄現(xiàn)象
這篇文章主要介紹了JavaScript中異步與回調(diào)的基本概念,以及回調(diào)地獄現(xiàn)象,本文主要介紹了異步和回調(diào)的基本概念,二者是JavaScript的核心內(nèi)容,需要所有熱愛JS的小伙伴深入了解,需要的朋友可以參考下2022-07-07
JavaScript實現(xiàn)拖動對話框效果的實現(xiàn)代碼
這篇文章主要介紹了JavaScript實現(xiàn)拖動對話框效果,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-10-10
JavaScript 進度條實現(xiàn)代碼(Firefox等相似瀏覽器下不支持)
JavaScript實現(xiàn)的進度條,可惜在Firefox等相似瀏覽器下不支持(遠程)2009-07-07
Avalonjs 實現(xiàn)簡單購物車功能(實例代碼)
avalon是國內(nèi)最強大的MVVM框架,最近小編在高購物車的項目,我們是用avalon來實現(xiàn)一些模塊的,所以順其自然的用avalon來實現(xiàn)購物車。接下來通過本文給大家分享Avalonjs 實現(xiàn)簡單購物車功能的實例代碼,需要的的朋友參考下2017-02-02
Jquery把獲取到的input值轉(zhuǎn)換成json
本篇文章主要介紹了Jquery把獲取到的input值轉(zhuǎn)換成json的相關(guān)知識,具有很好的參考價值。下面跟著小編一起來看下吧2017-05-05

