【面试题】说说你对 async和await 理解_前端面试题asycn和await

            function fn() {
                console.log('fn start')
                console.log('fn end')
            }
            async function run() {
                console.log('start 1')
                const res = await fn()
                console.log(res)
                console.log('end')
            }
            run()
            console.log('3')

运行结果为:

image-20230925154135052

结论:如果await 右边是一个函数,它会立刻执行这个函数,而且只有当这个函数执行结束后(即函数完成)!才会将async剩余任务推入微任务队列

image-20230925154401107

image-20230925154409457

**这是因为await等待的永远是promise,如果函数返回undefined,那么await会等待函数执行完成,将返回值转化为Promise.resolve(undefined) **(即第二种情况 await + 普通值)。如果函数执行完成后,返回一个失败的promise,那么它将不会再把剩余任务推入到微任务队列。

复杂点的案例,如果fn函数里面嵌套了await

案例:

async function async1() {
    console.log(1)
    await async2()
    console.log(2)
}

const async2 = async () => {
    await setTimeout((_) => {
        Promise.resolve().then((_) => {
            console.log(3)
        })
        console.log(4)
    }, 0)
}

const async3 = async () => {
    Promise.resolve().then(() => {
        console.log(6)
    })
}

async1()

console.log(7)

async3()


分析:

  • 首先调用async1 输出1 ,await async2()立刻调用async2(),直至async2函数完成后,才会将cl(2)推入微任务队列
  • 调用async2(), await 定时器,(定时器本身也是个函数),因此先将定时器的回调函数推入宏任务队列,定时器本身返回一个定时器ID

因此,async2可以转化为:

async ()=>{
	await 数值;  //即第二种情况
}

重点:await 数值会转化为await Promise.resolve(数值),再将async函数中剩余任务推入到微任务队列执行。这时候,async2函数中的剩余任务还有个return undefined,这代表async2函数并不能立刻执行完毕,会将return undefined推入到微任务队列中(这才代表着async2函数真正执行结束)

目前:宏任务队列:定时器回调函数任务

​ 微任务队列:return undefined(async2函数执行完毕)

  • 回到开始,await async2(),目前async2还没有执行结束,因此调用cl(7)
  • 调用async3(),微任务队列推入 cl(6)

目前:宏任务队列:定时器回调函数任务

​ 微任务队列:return undefined(async2函数执行完毕) cl(6)

  • 从微任务队列中取出第一个任务,return undefinedasync2()函数执行完毕,await async2() 转化为 Promise.resolve(undefined),因此将cl(2) 推入微任务队列

所以真正的结果是:1 7 6 2 4 3

image-20230925161025826

案例2:

async function async1() {
    console.log(1)
    await async2()
    console.log(2)
}

const async2 = async () => {
    await (async () => {
        await (() => {
            console.log(3)
        })()
        console.log(4)
    })()
}

const async3 = async () => {
    Promise.resolve().then(() => {
        console.log(6)
    })
}

async1()

console.log(7)

async3()

思路:

  • 首先跟开始一样,调用async1() 输出1,遇到await async2(),进入等待状态,等待async2()函数完成
  • 调用async2函数,遇到await 立即执行函数1,立即执行立即执行函数1,又遇到了await 立即执行函数2,继续执行立即执行函数2,输出3。同时立即执行函数2没有返回值,等同于return undefined。因此可以转化为
await Promise.resolve(undefined)

等待到了成功的promise,将cl(4)和立即执行函数1的返回值结果(return undefined)即立即执行函数1完成 推入到微任务队列

目前:宏任务队列:

​ 微任务队列:cl(4) return undefined(即立即执行函数1完成)

  • 因为async2函数内部 await 立即执行函数1,所以它需要等待立即执行函数1完成后,将async2函数执行完成推入微任务队列,再将cl(2)推入微任务队列
  • 输出7
  • 调用async3 ,将cl(6)推入微任务队列

目前:宏任务队列:

​ 微任务队列:cl(4) return undefined(即立即执行函数1完成) cl(6)

  • 同步任务完成,调用微任务队列任务,输出4,立即执行函数1完成,将async2完成推入微任务队列,将cl(2)推入微任务队列。

目前:宏任务队列:

总结

大厂面试问深度,小厂面试问广度,如果有同学想进大厂深造一定要有一个方向精通的惊艳到面试官,还要平时遇到问题后思考一下问题的本质,找方法解决是一个方面,看到问题本质是另一个方面。还有大家一定要有目标,我在很久之前就想着以后一定要去大厂,然后默默努力,每天看一些大佬们的文章,总是觉得只有再学深入一点才有机会,所以才有恒心一直学下去。

异步编程是现代软件开发中非常重要的一部分,而在JavaScript中,async和await是用来处理异步操作的两个关键字。下面是一些关于async和await面试题: 1. async和await是什么?它们的作用是什么? - async是用来声明一个函数是异步的,它会返回一个Promise对象。 - await用于等待一个Promise对象的解析结果,并且只能在async函数内部使用。它可以暂停函数的执行,直到Promise对象的状态变为resolved(已解决)。 2. async函数返回什么? - async函数始终返回一个Promise对象。这个Promise对象的结果取决于函数中的return语句。 3. 在什么情况下使用async和await? - 当需要处理异步操作时,可以使用async和await来编写更清晰、更易读的异步代码。 - 通常情况下,我们会将回调函数、Promise链式调用或者Generator函数转换为使用async和await的代码。 4. async函数中可以有多个await吗? - 是的,async函数中可以有多个await语句。每个await语句会暂停函数的执行,直到对应的Promise对象解析为已解决状态。可以按需使用多个await语句来处理多个异步操作。 5. async函数中如何处理错误? - 可以使用try-catch语句块来捕获和处理错误。在使用await等待一个Promise对象时,如果该Promise对象的状态变为rejected(已拒绝),则会抛出一个异常,可以通过try-catch来捕获并处理该异常。 这些面试题可以帮助你了解async和await的基本概念和用法。当然,还有更多的问题可以进一步探讨和学习。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值