首先說結論:
async 用來指定方法爲異步方法(區別於同步方法),即只有async修飾的函數中才能出現await阻塞操作,遇到阻塞是先讓CPU先執行函數外的操作,之後再回函數內部執行函數內接下來的代碼。而不像同步方法那樣傻傻的等待,浪費CPU資源
await阻塞,後面放異步任務,當其執行完畢後,阻塞該函數的執行,去執行函數外的代碼
例如:const response= await axios.get("/all") 注意這段代碼是從右邊開始執行,當前臺發出get請求後,await使得函數進入阻塞狀態(這時候response沒有賦值,因爲被await阻塞了),執行函數外的代碼。當get請求的數據回來後,函數繼續開始執行,這時候才賦值
前端代碼執行分成很多次時間循環:每一次時間循環的先後順序是執行宏任務,微任務,渲染UI
執行過程中遇到SetTimeOut之類的大型宏任務,那麼就把SetTimeOut內部的回調函數推入到下一個宏任務,當本輪循環全部完成後才繼續下一輪的執行
then函數內部是微任務,在本回合的宏任務執行完成後執行
<script>
async function async1(){
console.log('async1 start'+new Date().getTime())
await async2()
console.log('async1 end'+new Date().getTime())
}
async function async2(){
console.log('async2'+new Date().getTime());
}
console.log('script start'+new Date().getTime())
setTimeout(()=>{
console.log("settimeout"+new Date().getTime())
},500)
async1()
new Promise(function(resolve){
console.log("promise construction"+new Date().getTime())
resolve()
}).then(function(){
console.log('then 1'+new Date().getTime())
}).then(function(){
console.log('then 2'+new Date().getTime())
})
console.log("script end"+new Date().getTime())
</script>
首先執行setTimeOut,把裏面的回調函數推入到下一個宏任務,之後執行async1打印 async1 start
接下里執行async2,打印async2,當該函數執行完畢後,await使得async1阻塞轉而執行函數外的代碼
接下里執行Promise構造函數,打印promise construction,接下來執行then函數,由於then函數是微任務,所以要等待當前這一輪的所有的宏任務執行完成
接下來打印script end,這時候函數外的代碼都執行完成了,返回函數內執行被阻塞後的代碼,打印async 1
本輪所有的宏任務執行完畢,開始執行微任務,也是按照先後原則執行,所以先後打印then1 ,then2
本輪所有任務完成,開始執行下一輪的宏函數,打印settimeout
所以chrome瀏覽器多次輸出先後順序是
第一輪宏任務:
script start async1 start async2 promise construction script end async1 end
第一輪微任務:
then 1 then 2
第三輪宏任務:
settimeout