一些Promise、async/await的面试题

65 阅读2分钟

PrtScn_2023-11-08_21-25-00.png

异步任务不是直接放入任务队列,而是先放入对应的浏览器处理线程。当调用栈为空时,会通过事件循环去轮询任务队列,当1秒钟之后setTimeout的回调会放入到任务队列中,等事件循环轮询到之后将它放入调用栈中执行。

同步异步执行流程

PrtScn_2023-11-08_21-33-33.png

setTimeout(() => {
  console.log(l);
}, 20);
console.log(2);
setTimeout(() => {
  console.log(3);
}, 1);
console.log(4);
console.time("AA");
for (let i = 0; i < 90000000; i++) {
  // do soming
}
console.timeEnd("AA"); //=>AA: 33ms 左右
console.log(5);
setTimeout(() => {
  console.log(6);
}, 2);
console.log(7);
setTimeout(() => {
  console.log(8);
}, l0);
// 2 4 5 7 3 1 8 6
//字节面试题
async function async1() {
    console.log("A");
    await async2();
    console.log("B");
}
async function async2() {
    console.log("C");
}
console.log("D");
setTimeout(function () {
    console.log("E");
}, 0);
async1();
new Promise(function (resolve) {
    console.log("F");
    resolve();
}).then(function () {
    console.log("G");
});
console.log("H");
​
//D A C F H B G E

async await转换promise

await会等待这个promise的状态由pending转为fulfilled或者rejected。在此期间它会阻塞,延迟执行await语句后面的语句。

async function async1(){
    console.log("A");
    await async2();
    console.log("B");
}
//async中如果没有await,就和普通函数一样
async function async2(){
    console.log("C");
}
​
//转promise
function async1(){
    console.log("A");
    new Promise((resolve)=>{
        console.log("C");
        resolve();
    }).then((res)=>{
        console.log("B");
    })
} 

完整Event loop图解

PrtScn_2023-11-08_22-08-33.png

阿里面试题

<button id="button">点击</button>
<script>
    const button = document.querySelector("#button");
    button.addEventListener('click',()=>{
        Promise.resolve().then(()=> console.log("micro 1"));
        console.log('listener 1')
    });
    button.addEventListener('click',()=>{
        Promise.resolve().then(()=> console.log("micro 1"));
        console.log('listener 1')
    });
//1、浏览器窗口点击按钮
//2、执行下面语句
    button.click();
</script>
  1. 在浏览器窗口点击按钮,触发这两个点击事件的函数,相当于两个宏任务,先执行第一个宏任务中的代码,promise.then()进入微任务,执行打印listener 1,在执行微任务打印micro 1,接着向下执行第二个宏任务。所以打印顺序为 listener 1/micro 1/listener 2/micro 4
  2. 执行button.click(),相当于执行一个函数,创建函数上下文进栈,这个函数中存在两个函数,执行第一个函数,promise进微任务队列,执行打印listener 1,继续向下执行第二个函数,promise进微任务队列,执行打印listener 2,至此click函数执行完毕出栈,主线程栈空,执行微任务打印micro 1、micro 2。所以打印顺序为listener 1/listener 2/micro 1/micro 2