async和await你不知道的小细节

76 阅读2分钟

async和await是什么

async声明该函数是异步的,且该函数会返回一个promise。

await必须放在async函数中使用

  • await+Promise

await 会等待Promise的状态改为fullfilled,如果成功,那么会将async函数剩余任务推入到微任务队列,如果失败,那么剩余任务不会被推入微任务队列执行,它会返回Promise.reject(err)

  • await + 普通的值

即使await右边非函数,只是一个普通的数值,但它本质上是将其转化为 Promise.resolve(2),所以会返回一个成功的promise 

因此,当await等待到了成功的结果后,它会将async函数剩余内容推入到微任务队列中等待执行

  • await+函数

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

实例

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可以转化为:

    js
     代码解读
    复制代码
    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

94309ed2bd4047efb1a7c3921577d39b~tplv-k3u1fbpfcp-jj-mark_3024_0_0_0_q75.awebp

文章原链接:juejin.cn/post/728260…