https://blog.csdn.net/u014465934/article/details/99766790
我們這篇主要講瀏覽器和Nodejs環境下任務隊列的執行順序,尤其關注promise和async/await在任務隊列中的執行順序。
1.setTimeout、setImmediate、nextTick、Promise.next情況下
我們先記住幾條結論:
1.有process和setImmediate就考慮是在nodejs環境下
2.微任務中nextTick隊列在Promise.next前
3.宏任務中setTimeout在setImmediate前
4.所有可執行的微任務(包括nextTick和then)執行完畢之后,執行宏任務,注意宏任務隊列並不是全部執行,執行全部的setTimeout隊列中所有任務,再去執行對應產生的微任務,再去執行setImmediate,再去執行setImmediate產生的微任務。
我們先看一道題:
setTimeout(function(){
console.log(1)
},0);
new Promise(function(resolve,reject){
console.log(2);
resolve();
})
.then(function(){
console.log(3)
})
.then(function(){
console.log(4)
});
process.nextTick(function(){console.log(5)});
console.log(6);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
輸出2,6,5,3,4,1
參考文章:http://m.nowcoder.com/questions?uuid=aa9df421f9fe41d69139cbde19223294
我們再看一個復雜一點的:
console.log('1');
setTimeout(function() {
console.log('2');
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
process.nextTick(function() {
console.log('3');
})
})
process.nextTick(function() {
console.log('6');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9');
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
process.nextTick(function() {
console.log('10');
})
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
更復雜的可以看該篇文章(還有講解):https://www.jianshu.com/p/12b9f73c5a4f/
2.async/await執行順序
我們先記住幾條結論:
1.遇見await左側先執行,右側時候要跳出函數,等外部任務執行完再跳回
2.awati可以看成.then是一個微任務,放入微任務隊列,和其他微任務一樣,順序執行
3.執行微任務時,產生微任務順序放入當前微任務隊列,順序執行
4.遇見函數前面有async,awiat返回時,放入到Promise.then微任務隊列中,然后執行微任務隊列,如果前面沒有async,await返回時候直接執行,下次遇見await時候,再跳出執行微任務隊列
聲明:下面輸出結果,建議參考鏈接給出的答案,因為瀏覽器和Nodejs環境不同,設置不同瀏覽器和Nodejs版本不同,輸出結果就不同
再次注意參考給出的參考鏈接
async function async1() {
console.log( 'async1 start' )
await async2()
console.log( 'async1 end' )
}
async function async2() {
console.log( 'async2' )
}
async1()
console.log( 'script start' )
//輸出結果
async1 start
async2
script start
async1 end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
async function async1(){
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2(){
console.log('async2')
}
console.log('script start')
setTimeout(function(){
console.log('setTimeout')
},0)
async1();
new Promise(function(resolve){
console.log('promise1')
resolve();
}).then(function(){
console.log('promise2')
})
console.log('script end')
//輸出結果
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
async function testSometing() {
console.log("執行testSometing");
return "testSometing";
}
async function testAsync() {
console.log("執行testAsync");
return Promise.resolve("hello async");
}
async function test() {
console.log("test start...");
const v1 = await testSometing();
console.log(v1);
const v2 = await testAsync();
console.log(v2);
console.log(v1, v2);
}
test();
var promise = new Promise((resolve) => {
console.log("promise start..");
resolve("promise");
}); //3
promise.then((val) => console.log(val));
setTimeout(()=>{console.log("setTime1")},3000);
console.log("test end...")
//輸出結果
test start...
執行testSometing
promise start..
test end...
testSometing
執行testAsync
promise
hello async
testSometing hello async
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
async起什么作用:
async函數返回的是一個Promise對象,如果在函數return一個直接量,async會把這個直接量通過Promise.resolve()封裝成Promise對象。
await到底在等啥:
await在等async函數,但要清楚,它等的實際是一個返回值。注意到 await 不僅僅用於等 Promise 對象,它可以等任意表達式的結果,所以,await 后面實際是可以接普通函數調用或者直接量的。
await做了什么處理:
await后面的函數會先執行一遍,然后就會跳出整個async函數來執行后面js棧的代碼。等本輪事件循環執行完之后又會跳回到async函數中等待await。后面表達式的返回值,如果返回值為非Promise則繼續執行async函數后面的代碼,否則將返回的Promise放入Promise隊列(Promise的Job Queue)。
仔細閱讀下面參考文章:
https://segmentfault.com/a/1190000007535316
https://segmentfault.com/a/1190000011296839#articleHeader2
https://blog.fundebug.com/2018/12/10/understand-async-await-and-promise-by-8-pictures/
https://segmentfault.com/a/1190000015057278
3.宏任務產生宏任務/微任務,微任務產生宏任務/微任務執行的順序
微任務產生微任務會加入當前微任務隊列,順序執行。
宏任務產生宏任務,新的宏任務會放到下一個隊列,等當前宏任務下微任務執行完,再執行。
輔助圖進行理解:
可以參考:https://blog.csdn.net/u012925833/article/details/89306184#exp2-%E5%9C%A8%E5%BE%AE%E4%BB%BB%E5%8A%A1%E4%B8%AD%E5%88%9B%E5%BB%BA%E5%BE%AE%E4%BB%BB%E5%8A%A1
更多可以參考:
https://github.com/forthealllight/blog/issues/5
https://juejin.im/post/5b35cdfa51882574c020d685
https://juejin.im/post/5b73d7a6518825610072b42b
https://www.cnblogs.com/xiaohuochai/p/8527618.html
https://segmentfault.com/a/1190000012220307
https://juejin.im/post/5be5a0b96fb9a049d518febc
https://juejin.im/post/5b73d7a6518825610072b42b
https://www.jianshu.com/p/d207df1ca19e
https://juejin.im/post/59e85eebf265da430d571f89
————————————————
版權聲明:本文為CSDN博主「Cacra」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/u014465934/java/article/details/99766790
