• 使用await解决异步问题的注意点总结


    使用await解决异步问题的注意点总结

    项目中经常需要根据接口的返回值决定下一步操作promise, async/await时比较常见的处理异步操作的方法。本文主要是结合自己当前再项目中使用async/await的场景,说明在使用过程中应该注意的问题。

    1、await命令后面的promise对象的运行结果可能是rejected, 所以最好把await命令放在try···catch代码块中。

    // 好的方法,await在try···catch代码块中
        async handleOk (type) {
          try {
            this.btnLoading = true
            const res = await this.confirmDanger(type)
            this.btnLoading = false
            if (res.code === '0') {
              this.handle_remark = ''
              this.expert_check = '否'
              this.$emit('updateAlarmList', 'ok')
            }
          } catch (e) {
            this.btnLoading = false
            console.log(e)
          }
        }
    // 糟糕的方法,reject的情况下,没有异常处理
        async handleOk (type) {
          this.btnLoading = true
          const res = await this.confirmDanger(type)
          this.btnLoading = false
          if (res.code === '0') {
            this.handle_remark = ''
            this.expert_check = '否'
            this.$emit('updateAlarmList', 'ok')
          }
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    如上代码是常见的点击确认按钮进行的处理操作,为防止多次点击,给按钮增加了loading,如果await命令不在try···catch代码块,promise运行结果为rejected的情况下,不会执行await后面的代码,没有对异常情况进行处理,按钮就会一直在loading状态。

    2、多个await如果不存在继发关系,最好让他们同时触发

    // 好的方法,两个接口同时触发
        async handleOk () {
          try {
            this.btnLoading = true
            const [res1, res2] = await Promise.all([this.handleAlarm(), this.updateAlarm()])
            this.btnLoading = false
            if (res1.code === '0' && res2.code === '0') {
              this.remark = ''
              this.handleStatus = 1
              this.$emit('updateAlarmList', 'ok')
            }
          } catch (e) {
            this.btnLoading = false
            console.log(e)
          }
        },
     // 糟糕的方法, 两个接口继发执行,比较耗时
        async handleOk () {
          try {
            this.btnLoading = true
            const res1 = await this.handleAlarm()
            const res2 = await this.updateAlarm()
            this.btnLoading = false
            if (res1.code === '0' && res2.code === '0') {
              this.remark = ''
              this.handleStatus = 1
              this.$emit('updateAlarmList', 'ok')
            }
          } catch (e) {
            this.btnLoading = false
            console.log(e)
          }
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    如上代码中,点击确认按钮,会调用两个接口,根据两个接口的返回结果进行后续操作。这两个接口之前不存在继发关系,因此,好的方法是采用Promise.all使两个接口可以同时触发。

    3、await命令只能用在async函数中,在使用迭代器处理时需要注意

        async getImageUrl () {
          const textPromises = this.picUrlList.map(el => {
            await this.imageRedirect(el.fullUrl) // 报错,await用在普通函数
          })
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5

    上面的函数会报错,因为将await用在普通的函数中了,但是,如果将map方法改成async函数,也会有问题。

        getImageUrl () { // 这里不需要async
          const textPromises = this.picUrlList.map(async el => { // 这里使用async
            await this.imageRedirect(el.fullUrl)
          })
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5

    上面的代码可能不会正常工作,因为此时的请求会并发执行,而不是继发执行。

    如果想要多个请求继发执行,正确的方法是采用for循环,如下所示

        async getImageUrl () {
          for (let pic of picUrlList) {
            await this.imageRedirect(pic.fullUrl)
          }
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5

    如果确实希望多个请求并发执行,使用Promise.all方法,如下所示,下面两种方法效果相同

    方法一
        async getImageUrl () {
          const textPromises = this.picUrlList.(el => {
            const { data } = this.imageRedirect(el.fullUrl)
            return data
          })
          this.urls = await Promise.all(textPromise)
        },
    方法二
        async getImageUrl () {
          const textPromises = this.picUrlList.(el => {
            const { data } = this.imageRedirect(el.fullUrl)
            return data
          })
          this.urls = []
          for (const textPromise of textPromises) {
            this.urls.push({
              url: await textPromise
            })
          }
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    以上是在项目中使用await需要注意事项,包含了异常处理,多个异步操作并发执行、继发执行的场景,掌握这些注意事项,可以解决大部分异步出问题。

  • 相关阅读:
    C语言实现八种功能的通讯录(添加、删除、查找、修改、显示、排序、退出、清空)
    怎么给PDF添加页面?推荐三个PDF如何插入页面小妙招
    YOLOv8检测香蕉
    Oxidized-Docke配置
    Pytorch(二) —— 激活函数、损失函数及其梯度
    SpringBoot整合Gateway 的Demo(附源码)
    硫辛酸包裹CdS/ZnS硫化镉/硫化锌量子点
    (四) MdbCluster分布式内存数据库——业务消息处理
    lua学习
    最靠谱的nvm安装教程 for mac
  • 原文地址:https://blog.csdn.net/github_38851471/article/details/123048924