天天看点

setTimeout async/await promise执行顺序 详解

第一次面试,就挂在了 异步执行顺序上,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 ”的具体工作原理, 还是解释的不太清楚,本人还是小白,求大佬指正!

继续阅读