这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战
背景
学习前端三个月了,准备刷刷面试题,总结总结,一天几道面试题,向大厂进军。
问题
setTimeout、Promise、Async/Await 的区别
首先我们要知道这三个都是异步函数。当面试官问这个问题 的时候,我觉得他应该考的是Event Loop机制。
什么是Event Loop
Event Loop 是一个执行模型,在不同的地方有不同的实现。Android中有Event Loop,NodeJS中有Event Loop, 当然我们浏览器中也有EventLoop。
浏览器的Event Loop
我们用一张图来说明:
步骤:
- 执行全局Script代码(可以认为是一个宏任务);
- 全局Script代码执行过程中,产生异步任务,区分宏任务还是微任务,宏任务放宏任务队列,微任务放微任务队列。
- 全局Script同步代码执行完毕,调用栈Stack清空。
- 从微任务队列队首取一个微任务,放入调用栈Stack去执行,执行中间如果又产生微任务,直接放入当前正在执行的微任务队列末尾,这个时候微任务队列长度减1。
- 继续从微任务队首拿出一个微任务,放入调用栈Stack去执行;依次执行,直到微任务队列清空。
- 取出宏任务队首的一个宏任务去执行,放入Stack中执行,执行过程中如果有微任务产生,则放入新微任务队列。
- 当前的宏任务执行完毕以后,清空调用栈Stack;(注意这里不是宏任务队列执行完毕,是一个宏任务执行完毕)
- 重复执行4-7步骤。
再画一张图说明一下:
了解下浏览器宏任务和微任务有哪些
这里有个需要注意的地方UI rendering 这个虽然属于微任务,但是它的执行时机是由浏览器决定的。它的执行节点是在所有的微任务执行完毕,下一个宏任务开始之前,执行UI render。并不是说执行完所有的微任务以后,肯定会执行UI render,这个执行时机可能是下次所有微任务执行完毕,也可能是下下次,完全有浏览器决定。
自测一下,验证下我们所学的!
console.log("开始");
setTimeout(() => {
console.log("timeout-1");
// 第二步:
Promise.resolve().then(() => {
console.log("timeout-1:Promise=then");
Promise.resolve().then(() => {
console.log("timeout-1:Promise--Promise=then");
});
});
},0);
new Promise((resolve, reject) => {
console.log("Promise-resolve-before");
resolve(5);
console.log("Promise-resolve-after");
}).then((data) => {
console.log("Promise-resolve-then",data);
})
setTimeout(() => {
console.log("timeout-100");
},100);
async function async1() {
console.log('async1 start')
await async2();
console.log('async1 end')
}
async function async2() {
console.log('async2 end')
}
console.log("1");
async1();
console.log("结束");
答案揭晓:
开始=》Promise-resolve-before=》Promise-resolve-after=》1=》async1 start=》async2 end=》结束=》Promise-resolve-then 5 =》async1 end=》timeout-1=》timeout-1:Promise=then=》timeout-1:Promise--Promise=then=》timeout-100
结语
一步一步慢慢来,踏踏实实把活干!