前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >async/await

async/await

作者头像
hss
发布2022-02-25 20:02:49
2100
发布2022-02-25 20:02:49
举报
文章被收录于专栏:前端卡卡西前端卡卡西

async 函数的返回值

下面解释 async 关键字做了什么:

  • 被 async 操作符修饰的函数必然返回一个 Promise
  • 当 async 函数返回一个值时,Promise 的 resolve 方法负责传递这个值
  • 当 async 函数抛出异常时,Promise 的 reject 方法会传递这个异常值

await 操作符做了什么

  • await 后的值 v 会被转换为 Promise
  • 即使 v 是一个已经 fulfilled 的 Promise,还是会新建一个 Promise,并在这个新 Promise 中 resolve(v)
  • await v 后续的代码的执行类似于传入 then() 中的回调
代码语言:javascript
复制
async function foo() {
    await bar()
    console.log('foo')
}
async function bar() {
    console.log('bar');
}
foo()
new Promise(resolve => {
    console.log('p1');
    resolve();
}).then(function () {
    console.log('p2')
})

//chrome 84环境下结果:bar,p1,foo,p2

根据提示

代码语言:javascript
复制
async function async1(){
  await async2()
  console.log('async1 end')
}

等价于

代码语言:javascript
复制
async function async1() {
  return new Promise(resolve => {
    resolve(async2())
  }).then(() => {
    console.log('async1 end')
  })
}

RESOLVE(non-thenable)

​ 如果await 后面直接跟的为一个变量,比如:await 1;这种情况的话相当于直接把await后面的代码注册为一个微任务,可以简单理解为promise.then(await下面的代码)。然后跳出async1函数,执行其他代码,当遇到promise函数的时候,会注册promise.then()函数到微任务队列,注意此时微任务队列里面已经存在await后面的微任务。

代码语言:javascript
复制
async function foo() {
    console.log('foo')
    // var res = await 1
    // console.log('foo_end')
    // 上两条代码等价于
    return new Promise(resolve => {
        resolve(1)
    }).then(() => {
        console.log('foo_end')
    })
}
async function bar() { }

foo()

new Promise(function (resolve) {
    console.log('p1')
    resolve();
}).then(function () {
    console.log('p2')
})

//foo,p1,foo_end,p2

RESOLVE(thenable)

​ async2() 返回一个 promise, 是一个 thenable 对象,RESOLVE(thenable) 并不等于 Promise.resolve(thenable) ,而 RESOLVE(non-thenable) 等价于 Promise.resolve(non-thenable),下面几个例子可证明:

代码语言:javascript
复制
let p1 = new Promise(resolve => {
    resolve(1)
})
p1.then(() => {
    console.log(2)
})
let p2 = Promise.resolve().then(res => {
    console.log(3)
})
p2.then(() => {
    console.log(4)
}).then(() => {
    console.log(5)
})
//2,3,4,5
代码语言:javascript
复制
// let p1 = new Promise(resolve => {
//     resolve(1)
// })
// 等价于
let p1 = Promise.resolve(1)
p1.then(() => {
    console.log(2)
})
let p2 = Promise.resolve().then(res => {
    console.log(3)
})
p2.then(() => {
    console.log(4)
}).then(() => {
    console.log(5)
})
//2,3,4,5
代码语言:javascript
复制
let p1 = new Promise(resolve => {
    let p3 = Promise.resolve()
    resolve(p3)
})
p1.then(() => {
    console.log(2)
})
let p2 = Promise.resolve().then(res => {
    console.log(3)
})
p2.then(() => {
    console.log(4)
}).then(() => {
    console.log(5)
})
//3,4,2,5
代码语言:javascript
复制
let p1 = new Promise(resolve => {
    let p3 = Promise.resolve()
    resolve(p3)
})
p1.then(() => {
    console.log(2)
})
let p2 = Promise.resolve().then(res => {
    console.log(3)
})
p2.then(() => {
    console.log(4)
}).then(() => {
    console.log(5)
})
//3,4,2,5
代码语言:javascript
复制
let p1 = new Promise(resolve => {
    let p3 = Promise.resolve()
    // resolve(p3)
    // 等价于
    Promise.resolve().then(() => {
        Promise.resolve(p3).then(() => {
            resolve();
        })
    })
})
p1.then(() => {
    console.log(2)
})
let p2 = Promise.resolve().then(res => {
    console.log(3)
})
p2.then(() => {
    console.log(4)
}).then(() => {
    console.log(5)
})
//3,4,2,5

RESOLVE(thenable) 和 Promise.resolve(thenable)的转换关系

代码语言:javascript
复制
new Promise(resolve=>{
  resolve(thenable)
})

会被转换成:

代码语言:javascript
复制
new Promise(resolve => {
  Promise.resolve().then(() => {
    thenable.then(resolve)
  })
})

或者:

代码语言:javascript
复制
new Promise(resolve => {
    Promise.resolve().then(() => {
        Promise.resolve(thenable).then(() => {
          resolve()
        })
    })
})

await 将直接使用 Promise.resolve()相同语义

原题:

代码语言:javascript
复制
async function foo() {
    await bar()
    console.log('foo')
}
async function bar() {
    console.log('bar');
}
foo()
new Promise(resolve => {
    console.log('p1');
    resolve();
}).then(function () {
    console.log('p2')
})

上述代码在chrome 70会最终编译成:

代码语言:javascript
复制
async function foo() {
    // return new Promise(resolve => {
    //     resolve(bar())
    // }).then(() => {
    //     console.log('foo')
    // })
    // 上面的代码等价于
    return new Promise(resolve => {
        Promise.resolve().then(() => {
            bar().then(resolve)
        })
    }).then(() => {
        console.log('foo')
    })
}
async function bar() {
    console.log('bar');
}
foo()
new Promise(resolve => {
    console.log('p1');
    resolve();
}).then(function () {
    console.log('p2')
})

// 结果:p1,bar,p2,foo

而在chrome 73中,会编译成:

代码语言:javascript
复制
async function foo() {
    const p = bar()
    Promise.resolve(p).then(() => {
        console.log('foo')
    })
}
async function bar() {
    console.log('bar');
}
foo()
new Promise(resolve => {
    console.log('p1');
    resolve();
}).then(function () {
    console.log('p2')
})

//结果:bar,p1,foo,p2

​ 因为await规范的更新,导致了await bar()在chrome 70和chrome 73最终编译成的代码不一样,因此,结果也会不一样,如果不适用await 关键字,直接用原生的Promise语句就不会出现这个问题(因为await的就是promise语法糖,会最终编译成promise语句)。

参考以下文章:

令人费解的 async/await 执行顺序

async await 和 promise微任务执行顺序问题

async/await 原理及执行顺序分析

知乎贺老师的解答

这一次,彻底弄懂 Promise 原理

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-07-21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • async 函数的返回值
  • await 操作符做了什么
  • RESOLVE(non-thenable)
  • RESOLVE(thenable)
  • RESOLVE(thenable) 和 Promise.resolve(thenable)的转换关系
  • await 将直接使用 Promise.resolve()相同语义
  • 参考以下文章:
    • 令人费解的 async/await 执行顺序
      • async await 和 promise微任务执行顺序问题
        • async/await 原理及执行顺序分析
          • 知乎贺老师的解答
            • 这一次,彻底弄懂 Promise 原理
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档