js 單線程、宏任務與微任務的執行順序
js 單線程
眾所周知js是單線程,但js是可以執行同步和異步任務的,同步的任務眾人皆知是按照順序去執行的;
而異步任務的執行,是有一個優先級的順序的,包括了 **宏任務(macrotasks)**和 微任務(microtasks)
宏任務
是指消息隊列中的等待被主線程執行的事件,宏任務執行時都會重新創建棧,然后調用宏任務中的函數,棧也會隨着變化,但宏任務執行結束時,棧也會隨之銷毀。
包括 整體代碼script,setTimeout,setInterval ,setImmediate,I/O,UI renderingnew ,Promise*
微任務
可以把微任務看成是一個需要異步執行的函數,****執行時機是在主函數執行結束之后、當前宏任務結束之前****
包括 Promises.(then catch finally),process.nextTick, MutationObserver
微任務是基於消息隊列、事件循環、UI 主線程還有堆棧而來的
區別
宏任務和微任務的區別在於在事件循環機制中,執行的機制不同
每次執行完所有的同步任務后,會在任務隊列中取出異步任務,先將所有微任務執行完成后,才會執行宏任務
所以可以得出結論, 微任務會在宏任務之前執行。
我們在工作常用到的宏任務是 setTimeout,而微任務是 Promise.then注意這里是Promise.then,也就是說 new Promise在實例化的過程中所執行的代碼是同步的,而在 then中注冊的回調函數才是異步。
setTimeout(function(){ console.log('1') }); new Promise(function(resolve){ console.log('2'); resolve(); }).then(function(){ console.log('3') }); console.log('4'); new Promise(function(resolve){ console.log('5'); resolve(); }).then(function(){ console.log('6') }); setTimeout(function(){ console.log('7') }); function bar(){ console.log('8') foo() } function foo(){ console.log('9') } console.log('10') bar()
解析:
首先瀏覽器執行Js代碼由上至下順序,遇到setTimeout,把setTimeout分發到宏任務Event Queue中
new Promise屬於主線程任務直接執行打印2
Promis下的then方法屬於微任務,把then分到微任務 Event Queue中
console.log(‘4’)屬於主線程任務,直接執行打印4
又遇到new Promise也是直接執行打印5,Promise 下到then分發到微任務Event Queue中
又遇到setTimouse也是直接分發到宏任務Event Queue中,等待執行
console.log(‘10’)屬於主線程任務直接執行
遇到bar()函數調用,執行構造函數內到代碼,打印8,在bar函數中調用foo函數,執行foo函數到中代碼,打印9
主線程中任務執行完后,就要執行分發到微任務Event Queue中代碼,實行先進先出,所以依次打印3,6
微任務Event Queue中代碼執行完,就執行宏任務Event Queue中代碼,也是先進先出,依次打印1,7。
最終結果:2,4,5,10,8,9,3,6,1,7