关于循环里怎么正确使用await进行异步操作 资料

关于循环里怎么正确使用await进行异步操作

资料

如何在 JS 循环中正确使用 async 与 await

背景

在日常的项目开发中,常常遇到批量删除的应用场景,比如批量删除人员信息、设备信息、时间计划等。但是协议常常只给了单个删除的接口,而且设备那边同时只能处理一个相同的接口,所以使用异步+循环处理势在必行。本文就在讨论如何解决这个业务问题

问题

一开始我采用的是下面这种循环里嵌套异步处理,但是经过测试发现,deleteIOTChannel这条接口,实际上上条请求发出后,并未等待返回,下条请求就已经发出,所以下面这种在map循环里进行await 实际上是同步操作的

  aIdList.map(async (item) => {
                await _WebSDK.WSDK_SetDeviceConfig(
                    'deleteIOTChannel',
                    { channel: item },
                    {
                        type: 'DELETE'
                    }
                );
            });

 
 
  • 查阅资料

    按理来说,循环里面嵌套异步处理,应当是完全异步的,但是现在变成了同步操作,是不是和map()循环的原理有关系,我查阅了资料之后总结出以下知识点

    1.map循环的异步处理

    如果在map中使用await, map 始终返回promise数组,这是因为异步函数总是返回promise

    const mapLoop = async _ => {
      console.log('Start')
      const numFruits = await fruitsToGet.map(async fruit => {
        const numFruit = await getNumFruit(fruit);
        return numFruit;
      })
    

console.log(numFruits);

console.log(‘End’)
}

“Start”;
“[Promise, Promise, Promise]”;
“End”;

    如果你在 map 中使用 await,map 总是返回promises,你必须等待promises 数组得到处理。 或者通过await Promise.all(arrayOfPromises)来完成此操作。

    const mapLoop = async _ => {
      console.log('Start');
    

    const promises = fruitsToGet.map(async fruit => {
    const numFruit = await getNumFruit(fruit);
    return numFruit;
    });

    const numFruits = await Promise.all(promises);
    console.log(numFruits);

    console.log(‘End’)
    }

      2.for循环的异步处理

      在for循环中,过上使用getNumFruit来获取每个水果的数量,并将数量打印到控制台。

      由于getNumFruit返回一个promise,我们使用 await 来等待结果的返回并打印它。

      const forLoop = async _ => {
        console.log('start');
      

      for (let index = 0; index < fruitsToGet.length; index ++) {
      const fruit = fruitsToGet[index];
      const numFruit = await getNumFruit(fruit);
      console.log(numFruit);
      }
      console.log(‘End’)
      }

        当使用await时,希望JavaScript暂停执行,直到等待 promise 返回处理结果。这意味着for循环中的await 应该按顺序执行。

        结果正如你所预料的那样。

        “Start”;
        “Apple: 27”;
        “Grape: 0”;
        “Pear: 14”;
        “End”;
        
         
         

          这种行为适用于大多数循环(比如while和for-of循环)…

          解决方案

          由资料可得,异步处理写在map里还需要再处理一次才可以,所以我们采用正确写法是:在for循环里 才是真正的异步

                      for (let item in aIdList) {
                          try {
                              await _WebSDK.WSDK_SetDeviceConfig(
                                  'deleteIOTChannel',
                                  { channel: item },
                                  {
                                      type: 'DELETE',
                                      success: () => {},
                                      error: (xml, xhr) => {
                                          _oResponse.saveState(xhr);
                                      }
                                  }
                              );
                          } catch (error) {}
                      }
          
           
           

            在项目中实际测试,确实实现了异步处理,请求在上一个请求返回后才进行请求。

            总结
            从上面看出来什么
            如果你想连续执行await调用,请使用for循环(或任何没有回调的循环)。
            永远不要和forEach一起使用await,而是使用for循环(或任何没有回调的循环)。
            不要在 filter 和 reduce 中使用 await,如果需要,先用 map 进一步骤处理,然后在使用 filter 和 reduce进行处理。
            
             
             
              • 0
                点赞
              • 2
                收藏
                觉得还不错? 一键收藏
              • 0
                评论

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

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

              请填写红包祝福语或标题

              红包个数最小为10个

              红包金额最低5元

              当前余额3.43前往充值 >
              需支付:10.00
              成就一亿技术人!
              领取后你会自动成为博主和红包主的粉丝 规则
              hope_wisdom
              发出的红包
              实付
              使用余额支付
              点击重新获取
              扫码支付
              钱包余额 0

              抵扣说明:

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

              余额充值