先放上小姐姐的博客地址:https://www.cnblogs.com/zhengyeye/p/10774837.html。
這篇文章是看小姐姐的博客才讓自己對宏任務和微任務解決題目有了更多的認識的。
前端里面,很多很優秀的小姐姐,多多接近優秀的小姐姐,多多向她們學習。
言歸正傳
1.js是一個單線程的編程語言
意味着js在同一時間段只能做一件事,意味着它只有一個調用堆棧(call stack)。為什么呢?
因為js是瀏覽器腳本語言,主要用來主力與用戶進行的操作,操作DOM之類的事情。
如果她又多個線程,比如線程A想添加DOM節點,線程B想刪除節點就會亂套。
2.Event Loop(事件循環)
同步任務和異步任務分別進入不同的場所,同步進入主線程,異步進入Event Table並注冊回調函數,然后將其
移入Event Queue中,主線程內的任務執行完畢直至為空后,再去EventQueue讀取對應的函數,進入主線程。
上述任務不斷重復就是Event Loop(事件循環)。
3.宏任務和微任務
js中有兩類任務隊列:宏任務和微任務
宏任務:script(全局任務),setTimeout,setInterval,setImmediate,I/O,UI rendering
微任務:process.nextTick,promise,object.observer,MutationObserver
4.一些面試題
setTimeout(_=>console.log(4));
new Promise(resolve =>{
resolve();
console.log(1);
}).then(_=>{
console.log(3);
})
console.log(2);
setTimeout屬於宏任務,new Promise屬於同步任務,於是直接輸出1,
后面的.then()加入微任務中,接下來直接輸出2
微任務.then()比setTimeout先執行,故輸出3
最后輸出4
解析:
setTimeout的作用是等待給定的時間后為它的回調產生一個新的宏任務;
Promise.then則是具有代表性的微任務
new Promise在實例化的過程中所執行的代碼都是同步進行的,而then中注冊的回調才是異步執行
同步代碼執行完成后才回去檢查是否有異步任務完成,並執行對應的回調,而微任務又會在宏任務之前執行
setTimeout(function(){
console.log('定時器開始啦啦啦')
})
new Promise(function(resolve){
console.log('馬上執行for循環');
for(var i=0;i<10000;i++){
i==99&&resolve();
}
}).then(function(){
console.log('執行then函數')
});
console.log('代碼執行結束')
執行結果為:馬上執行for循環,代碼執行結束,執行then函數啦,定時器開始啦(解析同上)
console.log(1);
setTimeout(()=>{
console.log(2);
Promise.resolve().then(()=>{
console.log(3);
})
});
new Promise((resolve,reject)=>{
console.log(4);
resolve(5);
}).then((data)=>{
console.log(data)
})
setTimeout(()=>{
console.log(6)
})
console.log(7)
執行結果為1 4 7 5 2 3 6
執行全局Script,直接輸出1,后面的setTimeout為宏任務
new Promise相同於同步任務,輸出4,后面的.then()加入到微任務隊列中,后面的setTimeout為宏任務
接着執行全局Script,直接輸出7
執行完所有的宏任務后,接着在微任務隊列中的所有,輸出5
接着執行剩下的宏任務,輸出2
然后執行上一步紅任務產生的微任務,輸出3
最后執行最后一個setTimeout宏任務,輸出6
console.log('script start')
setTimeout(function(){
console.log('setTimeout')
},0)
Promise.resolve().then(function(){
console.log('promise')
}).then(function(){
console.log('promise2')
})
console.log('script end')
執行結果為
script start script end promise promise2 setTimeout
解析:
全局script任務,直接輸出script start ,script end
接下來執行微任務,輸出promise promise2
最后輸出setTimeout
所有的微任務總會在下一個宏任務之前全部執行完畢