第一次面试,就挂在了 异步执行顺序上,setTimeout async/await promise的执行顺序,搞不清楚,看了许多博客,但在关键点不是很详细。
可以先看一下大佬的解释: 网页链接
async function async1() {
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2')
}
console.log('script start')
setTimeout(() => {
console.log('setTimeout')
},0)
async1()
new Promise((resolve) => {
console.log('promise1')
resolve()
}).then(() => {
console.log('promise2')
})
console.log('script end')
//执行结果(不同浏览器执行结果可能不同,我用的谷歌))
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout
首先说一下相关基础概念
1.代码分为 “同步代码”,“异步代码”。
2.“异步代码”又可分为“宏任务”,与“微任务”;
3.代码执行优先级:同步代码 > 微任务 > 宏任务;
4. async/await :async 装饰的函数,会返回Promise对象,
await 装饰的语句,在语句执行完毕后,才会向下执行。
5. 微任务:Promise, async/await ……
6. 宏任务:setTimeout,setInterval,DOM事件……
7. 浏览器,每执行完一个任务,就 将所有代码队列遍历一遍,然后按代码优先级执行队列中的代码
过程分析:
1.由于 async1()与 async2() 没有调用;将 “console.log(‘script start’) ” 放入同步任务中;
同步任务:1.console.log('script start')
宏任务:
微任务:
2.向下,执行 setTimeout,将其放入 “宏任务队列”
同步任务:1.console.log('script start')
微任务:
宏任务:1. setTimeout()
3.async1()调用,进入async1函数
(1)将console.log(‘async1 start’)放入 同步任务队列
同步任务:1.console.log('script start')
2.console.log('async1 start')
微任务:
宏任务:1.setTimeout()
(2)执行 async2(),进入async2函数,并将console.log(‘async2’)放入“同步任务”
同步任务:1.console.log('script start')
2.console.log('async1 start')
3.console.log('async2')
微任务:
宏任务:1. setTimeout()
(3)执行完 async2,返回 await async2();这句代码;
注意 : 大坑出现!
由于 async2() 被 async 装饰,所以 async2()返回 一个 Promise对象。
await async2()
//相当于
// await Promise().then()
await async2()
}
将 then() 放入 微任务中
同步任务:1.console.log('script start')
2.console.log('async1 start')
3.console.log('async2')
微任务:1.then() //---async1()
宏任务:1. setTimeout()
由于 awiat 的存在,且 then() 并未执行,awiat 阻止了 console.log(‘async1 end’)的执行,直接跳出了async1(),开始执行new Promise();
4. 注意:new Promise()是同步代码,进入new Promise()
(1)将console.log(‘promise1’) 放入同步队列
同步任务:1.console.log('script start')
2.console.log('async1 start')
3.console.log('async2')
4.console.log('promise1')
微任务: 1.then() //---async1()
宏任务: 1.setTimeout()
(2)resolve(),表示 成功,它在 微任务队列中添加 函数,new Promise()的 .then 会调用这个函数
同步任务:1.console.log('script start')
2.console.log('async1 start')
3.console.log('async2')
4.console.log('promise1')
微任务: 1.then() //---async1()
2. then() // --- new Promise()
宏任务: 1. setTimeout()
5.最后 将 console.log(‘script end’) 放入 同步队列中
同步任务:1.console.log('script start')
2.console.log('async1 start')
3.console.log('async2')
4.console.log('promise1')
5.console.log('script end')
微任务:1.then() //---async1()
2. then() // --- new Promise()
宏任务:1.setTimeout()
6.执行过程
(1)先 顺序 执行 同步任务;
(2)执行 微任务;
注意:1.then() //—async1() 执行完毕会将 console.log(‘async1 end’)加入同步代码队列
同步任务://1.console.log('script start') 已执行
//2.console.log('async1 start') 已执行
//3.console.log('async2') 已执行
//4.console.log('promise1') 已执行
//5.console.log('script end') 已执行
6.console.log('async1 end')
微任务://1.then() //---async1() 已执行
2.then() // --- new Promise()
宏任务:1.setTimeout()
注意: 2.then() // — new Promise() 执行,会将console.log(‘promise2’)加入同步代码队列
同步任务://1.console.log('script start') 已执行
//2.console.log('async1 start') 已执行
//3.console.log('async2') 已执行
//4.console.log('promise1') 已执行
//5.console.log('script end') 已执行
//6.console.log('async1 end') 已执行
7.console.log('promise2')
微任务://1.then() //---async1() 已执行
// 2.then() // --- new Promise() 已执行
宏任务:1.setTimeout()
(3)再执行 宏任务 setTimeout(),将 console.log(‘setTimeout’)加入同步任务队列,并执行
同步任务://1.console.log('script start') 已执行
//2.console.log('async1 start') 已执行
//3.console.log('async2') 已执行
//4.console.log('promise1') 已执行
//5.console.log('script end') 已执行
//6.console.log('async1 end') 已执行
//7.console.log('promise2') 已执行
8.console.log('setTimeout')
微任务://1.then() //---async1() 已执行
// 2.then() // --- new Promise() 已执行
宏任务://1.setTimeout() 已执行
大概流程就是如此,但 “await ”的具体工作原理, 还是解释的不太清楚,本人还是小白,求大佬指正!