promise、async/await在任务队列中的执行顺序


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


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM