您的位置:首页 > 大数据 > 人工智能

Promise、Async\Await、setTimeout的执行顺序

2020-03-09 23:13 781 查看

先来看一道经典面试题

转载(https://juejin.im/post/5b03e79951882542891913e8)
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')

弄明白执行顺序要掌握的知识点

  1. JS事件循环机制
  2. Promise(阮老师:http://es6.ruanyifeng.com/#docs/promise
  3. Async\Await(阮老师:http://es6.ruanyifeng.com/#docs/async
  4. 异步任务(微任务、宏任务)[ 微任务优先于宏任务执行 ]

以下事件属于宏任务:

setInterval()
setTimeout()

以下事件属于微任务

new Promise()
new MutaionObserver()
我的理解
*JS是单线程,所以浏览器再解析上面那段代码的时候会自上往下解析,因此
第一输出:script start,
接着继续往下执行,这时会遇到 setTimeout() ,js会将该函数放入任务队列的宏任务队列。
接着继续往下执行,遇到 async1(),执行 async1() 函数
第二输出:async1 start,
继续往下执行,遇到 await async2() ,此时会先返回一个属于async1() 的Promise对象,并且会放入微任务队列
接着执行async2(),该函数也是一个 async 函数,所以也会返回一个Promise 对象,并且会放入微任务队列*
第三输出:async2
如果疑惑输出 async2 后为什么不接着输出 async1 end?
因为 async 函数遇到 await 会先返回,得等到await后面的异步任务执行完才会执行后面的语句。具体看阮老师写的ES6
到此异步任务结束,继续往下执行,遇到 new Promise()
该函数会立即执行,因此
第四输出:promise1
继续往下执行,遇到 resolve() 函数,该函数是回调函数,所以放入微任务队列,,.then()也是回调,放入微任务队列。
继续往下执行,遇到  console.log('script end')。
第五输出:script end
此时主线程都执行完毕,然后去异步任务队列调用异步任务,但是要遵循两个原则:
微任务优先宏任务、先进先出。
因此:先执行 async1()  函数返回的Promise对象,因为没又返回值,所以什么也不会打印。
再执行 async2()  函数返回的Promise对象,同样什么也不打印。
第六输出:async1 end
然后再去找 new Promise()  返回的 Promise 对象,执行. then()  方法,
第七输出:promise2
第八输出:setTimeout
setTimeout  属于宏任务,因此最后输出。
总结

由于js是单线程,因此浏览器中 js引擎 在解析 js代码 的时候默认会自上而下解析,如果遇到异步事件(setTimeout、ajax等)会分类放入对应的异步任务队列(Event Loop)中,等主线程上同步程序都执行完毕,主线程会去异步任务队列中按照规则找出异步事件并执行。

正确的执行顺序

script start、async1 start、async2、promise1、script end、async1 end、promise2、setTimeout

  • 点赞
  • 收藏
  • 分享
  • 文章举报
Zgl1992 发布了4 篇原创文章 · 获赞 0 · 访问量 969 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: