彻底搞懂 async await 的return问题

什么是async await?

简单的来说 async await就是promise的语法糖,我们可以把它认知为promise的简写,另外你可以将它简单的认为是异步转同步的那么一个解决方案。

Async?

首先我们来看这一串代码

//立即执行函数,不了解的话可以去查一下资料
const a = (async () => {
  return 111
})()
console.log(a) // Promise { 111 }

我们可以看到给函数添加上async之后 返回值即成为了promise对象,正如async译文一样,异步,也就是说我们把这个函数变成了异步promise函数。此时我们再去return 一个值的话,并不会是我们想的那个结果。
当然如果单纯的添加一个async并不是这个函数就成为异步了,不要那么去想,那么去想你就错了

console.log('first') //1
  ; (async () => {
    console.log('tow') //2
  })()
console.log('last') //3

如上所示,async函数并没有像异步计时器settimeout一样,挂起,当last执行完成之后再去执行,而是直接输出了,所以我们不要理所当然的去想加上了 async,这个函数就成异步函数了。
当然如果我们不return的话,就是返回一个空的promise对象,其实如果不做啥特殊操作的话,async自己单独使用的话,其实不是特别能显示出它的作用。

Await?

这个时侯我们就应该想到 await了,await是什么?如果promise对象通过then或catch方法又注册了回调函数,async函数执行完以后,注册的回调函数就会放到异步队列中,等待执行。如果只是async, 和promise 差不多,但有了await就不一样了, await 关键字只能放到async 函数里面,await是等待的意思,那么它等待什么呢,它后面跟着什么呢?其实它后面可以放任何表达式,不过我们更多的是放一个返回promise 对象的表达式,它等待的是promise 对象的执行完毕,并返回结果,我们先来尝试这放一个异步fs读取

console.log('first') //
  ; (async () => {
    // 异步读取
    const fs111 = await fs.readFile('云开发.txt', function (err, data) {
      if (err) {
        return console.error(err)
      }
      return data.toString()
    })
    console.log(fs111)
  })()
console.log('last') //

在这里插入图片描述
我们的结果是返回的undefined。那是为什么呢?正如我们上方所说,await等待的是一个promise对象,那么我们的fs是promise对象么,显然并不是,所以await并没有阻塞后方代码执行,因为被挂起了确切地说fs并没有执行完,还没有返回数据data还是空的,所以结果就是空。
解决的办法也很简单,将fs封装成一个promise就可以了,再去执行,console.log()输出就会显示,读取的文件数据。

那么好,简单的介绍完async和await之后,我们其实应该知道最常用的场景是在哪里,其实就是发送ajax请求

这里的请求是 axios 获取数据,然后存入到vue的data中

    async leftMenu() {
      const { data: res } = await this.$http.get('menus')
      this.menuList = res.data
    }

因为axios本身返回的就是一个promise对象,await接受的就是成功之后的回调函数数据,在获取到数据之后,我们将其赋值给data中的menuList,这样扎眼一看其实没什么问题,但是我们换种思路 因为本身 async是一个函数那么我们可不可以将获取到的值return出去,然后再从像created中,mounted中直接用this.menuList = leftMenu()呢?

我们可以来模拟尝试一下

const res = async function (a) {
  let xiao = await new Promise((resolve, reject) => {
    setTimeout(() => {
      if (a === 0) {
        resolve('你成功获取了数据')
      } else {
        reject('获取数据失败了')
      }
    }, 3000)
  })
  // console.log(xiao)
  return xiao
}

const xiaores = res(0)
console.log(xiaores)

在这里插入图片描述
结果发现返回的数据是promise,并不是我们想的返回一个你成功获取了数据,这是为什么呢?因为你这个时候要清楚await是promise的语法糖呀!就相当于.then呀,那么then的话,是不是就是异步代码了?这跟settimeout没关系,要知道.then也会被挂起,那么await就不会被挂起了么?我们知道他是一个异步函数之后,执行的是promise,那么他就会去执行,下方的同步代码,这也就导致了,数据其实还没有返还回来,导致无法将异步返回的数据赋值给我们我们想赋予的哪一个值。

解决它也很简单

const res = async function (a) {
  let xiao = await new Promise((resolve, reject) => {
    // setTimeout(() => {
    if (a === 0) {
      resolve('你成功获取了数据')
    } else {
      reject('获取数据失败了')
    }
    // }, 3000)
  })
  // console.log(xiao)
  return xiao
}
  ; (async function (a) {
    const xiaores = await res(0)
    console.log(xiaores)
  })()

在这里插入图片描述
其实你就可以简单的理解就是调用了他的then方法

const res = async function (a) {
  let xiao = await new Promise((resolve, reject) => {
    // setTimeout(() => {
    if (a === 0) {
      resolve('你成功获取了数据')
    } else {
      reject('获取数据失败了')
    }
    // }, 3000)
  })
  // console.log(xiao)
  return xiao
}
res(0).then(res => {
  const xiaores = res
  console.log(xiaores)
})

得到的结果是一样的
总结,其实async await可以return,但是要经历多次嵌套,所以说能别return就别return了。
再给大家放一下今天下午遇到的错误

在这里插入图片描述
这其实也是向我们刚才那样,return 一个值,让那后用变量接收,但是返回的值确是空?
因为什么?因为return放在了forEach里,return放在forEach里是没有用的,我们的函数其实并没有返回值,所以结果是空。这个bug,差点整的我怀疑让人生,让我又一次的怀疑,我对async以及await的认知。
所以说写代码还是要认真,加油吧小伙伴么!

提及一下,如果我们想要去遍历中停止请使用 for循环或者 for in for of,甚至 some,every,fliter,map,这些都是可以的,如需了解请关注后续文章

  • 27
    点赞
  • 77
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

归来巨星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值