Skip to content

async 函数本身会返回一个 Promise

async await 函数处理异步回调比 Promise 的 then 函数更优雅、简洁,所以我比较喜欢前者。

回到正题,本文在这里聊一聊 async await 函数的执行顺序问题。本人曾经对此非常疑惑。

用伪代码理解 async await

  • 其实 async 函数本身会返回一个 Promise。

  • 其实 async、await 就是 Promise 和 generator 函数的语法糖。

为了帮助理解,举个例子:

下面这个 async function speak 函数,如果使用 Promise + then 函数的形式是这样的:(可以这样粗浅的理解)

async 函数:

js
async function speak() {
  const res = await new Promise(resolve => {
    setTimeout(() => {
      resolve('11')
    }, 1000)
  })
  return res
}

转换为 Promise + then 函数形式:

js
function speak() {
  return new Promise(o_resolve => {
    new Promise(i_resolve => {
      setTimeout(() => {
        i_resolve('11')
      }, 1000)
    }).then(value => {
      // 伪代码
      // 将 return 的返回值作为成功值(resolve value),更改 Promise 的状态。
      // const res = (return 的返回值)
      o_resolve(res)
    })
  })
}

实际的一个例子

执行 main 函数,过了多久会打印 res1 和 res2 呢?

js
main()

async function main() {
  // 如果 speak1 和 speak2 前面不加 await,那么打印的是两个未知状态的 Promise
  // const res1 = speak1()
  // const res2 = speak2()
  const res1 = await speak1()
  const res2 = await speak2()
  console.log(res1, res2)
}

async function speak1() {
  const res = await new Promise(resolve => {
    setTimeout(() => {
      resolve('1')
    }, 1000)
  })
  return res
}

async function speak2() {
  const res = await new Promise(resolve => {
    setTimeout(() => {
      resolve('2')
    }, 1000)
  })
  return res
}

在上面的代码中,两秒后正确的打印 1、2

image.png 如果在 speak1()、speak2() 函数前面没有加上 await 关键字,那么打印的将是两个未知状态的 Promise。

image.png

结论

  • 虽然 async await 很好,但是 async await 处理错误也可能会导致写很多 try catch 代码,导致不那么优雅、简洁。如果真的不想看到有那么多 try catch,可以考虑使用 await-to-js 库。

  • async 函数本身会返回一个 Promise,所以如果想要等这个函数执行完后再执行后面的代码,它的前面必须加上 await。

Released under the MIT License.