JS異步的執(zhí)行順序分析
- 1.js的執(zhí)行順序,先同步后異步
- 2.異步中任務隊列的執(zhí)行順序: 先微任務microtask隊列,再宏任務macrotask隊列
- 3.調(diào)用Promise 中的resolve,reject屬于微任務隊列,setTimeout屬于宏任務隊列
注意以上都是 隊列,先進先出。
微任務包括 `process.nextTick` ,`promise` ,`MutationObserver`。
宏任務包括 `script` , `setTimeout` ,`setInterval` ,`setImmediate` ,`I/O` ,`UI rendering`。
在node環(huán)境下,process.nextTick的優(yōu)先級高于Promise,也就是可以簡單理解為:在宏任務結束后會先執(zhí)行微任務隊列中的nextTickQueue部分,然后才會執(zhí)行微任務中的Promise部分。
javascript事件機制
題目1:
console.log('script start') async function async1() { await async2() console.log('async1 end') } async function async2() { console.log('async2 end') } async1() setTimeout(function() { console.log('setTimeout') }, 0) new Promise(resolve => { console.log('Promise') resolve() }) .then(function() { console.log('promise1') }) .then(function() { console.log('promise2') }) console.log('script end')
執(zhí)行結果?
分析:
首先執(zhí)行 同步代碼:
- 1. 首先執(zhí)行 console.log('script start')
- 2. 執(zhí)行 async1() 的時候,馬上執(zhí)行了 async2函數(shù):console.log('async2 end')
- 3. 順序執(zhí)行 new Promise()中的同步函數(shù):console.log('Promise')
- 4. 最后執(zhí)行 console.log('script end')。
上面是同步執(zhí)行的代碼,然后看剩下的異步執(zhí)行的代碼:
首先,setTimeout是 宏觀任務,排除到最后,剩下微觀任務:
async function async1() { await async2() console.log('async1 end') } new Promise(resolve => { resolve() }) .then(function() { console.log('promise1') }) .then(function() { console.log('promise2') })
- 5. 然后根據(jù)先入先出的對列方式,先執(zhí)行await async2() 后面阻礙的函數(shù)console.log('async1 end')
- 6. 執(zhí)行promise的resolve函數(shù)
new Promise(resolve => { resolve() })
也就是接下來的兩個then:console.log('promise1') ----console.log('promise2') ;
- 7. 最后執(zhí)行的是 setTimeout函數(shù)console.log('setTimeout') ;
綜上所述,以上代碼執(zhí)行的順序是:
1.script start >> 2.async2 end >> 3.Promise >> 4.script end >> 5.async1 end >> 6.promise1 >> 7.promise2 >> 8.setTimeout
題目2:
(function() { setTimeout(() => { console.log(0); }); new Promise(resolve => { console.log(1); setTimeout(() => { resolve(); Promise.resolve().then(() => console.log(2)); console.log(3); }); Promise.resolve().then(() => console.log(4)); }).then(() => { console.log(5); Promise.resolve().then(() => console.log(8)); setTimeout(() => console.log(6)); }); console.log(7); })();
- 1. 同樣先執(zhí)行同步代碼,且先把setTimeout去掉:
new Promise(resolve => { console.log(1); Promise.resolve().then(() => console.log(4)); //微觀任務 }).then(() => { //then函數(shù)是執(zhí)行對應的 resolve 的時候才執(zhí)行的 console.log(5); Promise.resolve().then(() => console.log(8));//微觀任務 }); console.log(7);
可以看出先執(zhí)行:console.log(1);console.log(7);
- 2. 執(zhí)行微任務
Promise.resolve().then(() => console.log(4));
代碼變成了:
(function() { setTimeout(() => { console.log(0); }); new Promise(resolve => { setTimeout(() => { resolve(); Promise.resolve().then(() => console.log(2)); console.log(3); }); }).then(() => { console.log(5); Promise.resolve().then(() => console.log(8)); //這句是多加的 setTimeout(() => console.log(6)); }); })();
只剩下宏觀任務(微觀任務在宏觀任務里,也就是宏觀任務外面不在有微觀任務了)
- 3. 執(zhí)行console.log(0);
- 4.再執(zhí)行 new Promise 中的 setTimeout,先執(zhí)行里面的同步函數(shù):console.log(3)
- 5. 再執(zhí)行上面的 resolve,對應的是下面的then函數(shù):
then(() => { console.log(5); Promise.resolve().then(() => console.log(8)); //這句是多加的 setTimeout(() => console.log(6)); }
所以先執(zhí)行console.log(5);
剩下的都是微觀任務和宏觀任務,先看微觀任務:
new Promise(resolve => { resolve(); Promise.resolve().then(() => console.log(2)); }).then(() => { Promise.resolve().then(() => console.log(8)); setTimeout(() => console.log(6)); });
所以根據(jù)隊列中的微觀任務順序先執(zhí)行:console.log(2),在執(zhí)行then中的console.log(8);
最后再執(zhí)行 console.log(6)
綜上所述,結果為
1/7/4/0/3/5/2/8/6
題目3:
(function() { setTimeout(() => { console.log(0); }); new Promise(resolve => { console.log(1); setTimeout(() => { resolve(); Promise.resolve().then(() => { console.log(2); setTimeout(() => console.log(3)); Promise.resolve().then(() => console.log(4)); }); }); Promise.resolve().then(() => console.log(5)); }).then(() => { console.log(6); Promise.resolve().then(() => console.log(7)); setTimeout(() => console.log(8)); }); console.log(9); })();
解釋如下:【同步>異步;微任務>宏任務】第一步:打印出1、9;如圖
圖a
由圖a中的任務隊列可知:
第二步: 執(zhí)行微任務3,打印出5;
第三步:執(zhí)行宏任務1,打印出0,
第四步:開始執(zhí)行宏任務2;如圖:
圖b
第五步:由圖b中的任務隊列可知, 執(zhí)行微任務4,打印出6,如圖:
圖c
第六步:由圖c中的任務隊列可知, 執(zhí)行微任務5,打印出2;如圖
圖d
由圖d的任務隊列可知,
第七步:執(zhí)行微任務6,打印出7;
第八步:執(zhí)行微任務9,打印出4;
第九步:執(zhí)行宏任務7,打印出8;
第十步:執(zhí)行宏任務8,打印出3;
即答案是:
1-9-5-0-6-2-7-4-8-3
到此這篇關于JS異步執(zhí)行順序的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
JavaScript?中的單例內(nèi)置對象Global?與?Math
這篇文章主要介紹了JavaScript?中的單例內(nèi)置對象Global與Math,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-07-07JavaScript中輸出信息的方法(信息確認框-提示輸入框-文檔流輸出)
這篇文章主要介紹了JavaScript中輸出信息的方法(信息確認框-提示輸入框-文檔流輸出)的相關資料,需要的朋友可以參考下2016-06-06ES6使用 Array.includes 處理多重條件用法實例分析
這篇文章主要介紹了ES6使用 Array.includes 處理多重條件用法,結合實例形式分析了Array.includes基本功能、原理及處理多重條件相關操作技巧,需要的朋友可以參考下2020-03-03絕對經(jīng)典的滑輪新聞顯示(javascript+css)實現(xiàn)
這篇文章主要介紹了絕對經(jīng)典的滑輪新聞顯示(javascript+css)實現(xiàn),需要的朋友可以參考下2007-03-03微信小程序本地存儲實現(xiàn)每日簽到、連續(xù)簽到功能
這篇文章主要介紹了微信小程序本地存儲實現(xiàn)每日簽到、連續(xù)簽到功能,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-10-10PhotoShop給圖片自動添加邊框及EXIF信息的JS腳本
這篇文章主要介紹了PhotoShop給圖片自動添加邊框及EXIF信息的JS腳本,本文給出效果圖和實現(xiàn)代碼,需要的朋友可以參考下2015-02-02