关于async和await

Frank
  • 开发笔记
  • JS
大约 3 分钟约 901 字...

发现问题

某天在牛客上刷到这样一道题:

async function getData() {
  return await Promise.resolve('I made it!')
}
const data = getData()
console.log(data)

问输出结果是什么?我想这也太简单了,肯定是返回一个成功状态的 Promise 啊,一看答案我傻了,居然是一个未解决的 Promise.

最后我好好想了想,之前的理解一直是错的。看了几篇大牛的文章,我学废了

问题分析

看回上面那段代码,async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。 当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。但是最重要的一点是异步函数 async 始终返回一个 promise。其实这段代码这样写可能更好理解:

async function getData() {
  const res = await Promise.resolve('I made it!')
  return res
}
const data = getData()
console.log(data)

当调用getData()的时候,遇到了await那么就会暂停在这一行,等待后面的Promise返回结果,getData()会先返回,此时返回的肯定是一个Promise而且是等待状态的。接着执行调用getData()之后(async 函数调用不会造成阻塞,它内部所有的阻塞都被封装在一个 Promise 对象中异步执行)的代码,那么这行代码console.log(data)便会紧跟着执行,此时打印的结果肯定是一个处于等待状态的Promise

data.then((res) => console.log(res)) // I made it!

这段代码可能也会让人困惑:

async function getData() {
  console.log('async执行开始')
  return await Promise.resolve('123')
}
const data = getData()
console.log(data)
const c = data.then((res) => {
  console.log(res)
})
console.log(c) // 这里也打印的是一个等待状态的Promise

其实是一样的,分析以下这段代码的执行顺序:调用 getData(),打印async执行开始,遇到 await,先返回。打印 data,一个等待状态的 Promise,先执行同步代码,打印 c,结果一样。返回去执行异步任务,先清掉所有微任务,async 返回了成功状态的 Promise 且参数为123,接着执行 then 里面的代码,打印出123

备注

async 函数和普通 函数没有什么不同,他只是表示这个函数里有异步操作的方法,并返回一个 Promise 对象 翻译过来其实就是:

// async/await 写法
async function async1() {
  console.log('async1 start')
  await async2()
  console.log('async1 end')
}
// Promise 写法
async function async1() {
  console.log('async1 start')
  // 如果传入的参数是Promise对象,则参数的结果决定了Promise.resolve()的结果
  Promise.resolve(async2()).then(() => console.log('async1 end'))
}

async function async2() {
  console.log('async2')
}

显然,await后面的代码,实际上相当于Promisethen里面的代码

await 会暂停代码在该行上,直到 promise 完成,然后返回结果值。在暂停的同时,其他正在等待执行的代码就有机会执行了。

如果在函数中 return 一个直接量,async 会把这个直接量通过 Promise.resolve() 封装成 Promise 对象。

还有一点就是如果 async 函数没有返回值,又该如何?很容易想到,它会返回 Promise.resolve(undefined)

参考文章

上次编辑于:
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.14.1