上图是浏览器事件循环的思维导图。
event loop の步骤
- 先将全局Script同步代码直接压入调用栈执行(遵循先进后出),异步回调事件先放入事件队列(遵循先进先出);
- 同步代码执行完毕之后,调用栈stack会清空。
- 从微任务队列microtask queue取出队首的回调任务压入调用栈执行,依次将微任务队列回调任务执行完毕。如果在执行microtask的过程中,又产生了microtask,那么会加入到队列的末尾,也会在这个周期被调用执行。
- 微任务执行完毕以后,从宏任务队列macrotask queue取出队首的回调任务压入调用栈stack执行,且在每次宏任务执行完毕之后检查微任务队列microtask queue中是否有回调任务,有就先将微任务全部执行完毕再重复当前步骤。
(简而言之,先同步再异步,异步中先微再宏,宏中还要检查微)
当event loop遇上async await
async await是什么以及解决了什么问题?
字面意思来理解,async 是“异步”的简写,而 await 是 async wait 的简写可以认为是等待异步方法执行完成。
实际上,async/await 在底层转换成了 promise 和 then 回调函数。也就是说,这是 promise 的语法糖。每次我们使用 await, 解释器都创建一个 promise 对象,然后把剩下的 async 函数中的操作放到 then 回调函数中。async/await 的实现,离不开 Promise。
我们创建了 promise 但不能同步等待它执行完成,我们只能通过 then 传一个回调函数这样很容易再次陷入 promise 的回调地狱。而async/await就是来解决这个回调地狱。
async await在event loop中的地位?
上文也提到了await前面的代码相当于是promise中.then前面部分,await后紧跟的代码相当于then的回调函数即微任务。
趁热打铁练习题 try 一 try~
console.log('1')
async function async1() {
console.log('2')
let a = await "3"
console.log(a)
console.log('4')
}
async1()
console.log('5')
从上至下,输出1,输出2,遇到await,await相当于创建了一个promise对象,将它后面紧跟的值或函数包裹(这里是同步任务),并将后两行代码放入then回调函数中(这里是微任务)即放入微任务队列,然后输出5,同步任务执行完毕之后,优先执行微任务,即输出3,4。
console.log(1)
new Promise(function(resolve){
console.log(3)
resolve(100)
}).then(function(data){
console.log(data)
}).then(function(){
console.log(200)
})
setTimeout(function(){
console.log(4);
})
setTimeout(function(){
console.log(5);
})
console.log(2)
1,3,2,100,200,4,5,懂得都懂,lol