【问题标题】:How to use async/ await for a 'for statement' only如何仅将 async/await 用于“for 语句”
【发布时间】:2021-12-31 21:42:22
【问题描述】:

我想使用异步函数“submitToTheOthers”,我想从let items = [] 开始,它会在“submitToTheOthers”完成后运行。但它并没有等到“submitToTheOthers”完成。可能是因为“submitToTheOthers”中没有等待。因此,我想在 'submitToTheOthers' 中做出 for 声明,就像 await 一样,但我不知道如何。

我可以在“updateGeneralInfoToOther”处使用 await,但后来我无法运行 几乎同时为所有服务器更新GeneralInfoToOther,如果其中一个服务器出现错误,那么我无法在for语句中从服务器运行。我想使用 await 或 promise 之类的声明或更大的范围。

什么是让它等待'submitToTheOthers'的好方法?

ps)我希望了解旧语法,因为我可能需要在 Internet Explorer XD XD TT 上使用它

Settings.vue

<template>
  <div>
    <button class="point" @click="submitTotalServer()">submitTotalServer</button>
  </div>
</template>
<script>
import {
  updateGeneralInfoToOther,
} from '@/api/settings'
export default {
  data() {
    return {
      serverNames: ['a server', 'b server'],
      idxs: [0,1],
      serverFullAddress: ['http://localhost:12345','http://randomUrl:12345' ]
      serverResCheck: [],
    }
  },
methods: {
    async submitTotalServer() {
      await this.submitToTheOthers()  // this function      
      
      let items = []  // here
      for(let i=0; i< this.idxs.length ; i++){
        if(!this.serverResCheck[i]){
          items.push(this.serverNames[i])
        }
      }
      if(items == []){
        alert('saved in all servers')
      }else{
        alert(`[${items}] Error`)
      }
      
    },
    async submitToTheOthers(){
      let data = {
        data : 'test',
      }
      
      for (let i=0; i< this.idxs.length ;i++){
          updateGeneralInfoToOther(1, data, this.serverFullAddress[i]').then((res) => // axios function 
          {
            if (res.status == 200) {
              this.serverResCheck[i]= true
            }else{
              this.serverResCheck[i]= false
            }
          })
        }
      }
    },
</script>

api/settings.js

// ...
export function updateGeneralInfoToOther(id, data, serverAddress) {
  axios.defaults.timeout = 5000;
  data.serverAddress = serverAddress
  
  return axios.post(`/api/settings/generalToOther/${id}`, data)
}
// ...

【问题讨论】:

  • 可能是因为你没有退货?
  • link

标签: javascript vue.js


【解决方案1】:

问题的症结在于您的for 循环没有等待updateGeneralInfoToOther() 返回的承诺解决。为了让您的代码正常工作,这是强制循环到await 的快速修复,即:

for (let i=0; i< this.idxs.length ;i++) {
    await updateGeneralInfoToOther(1, data, this.serverFullAddress[i]).then((res) => {
        if (res.status == 200) {
            this.serverResCheck[i]= true
        } else {
            this.serverResCheck[i]= false
        }
    })
}

但是,这个解决方案并不理想,因为您必须单独等待每个请求:确实没有理由这样做。更好的解决方案是简单地一起执行所有这些异步操作,然后等待所有这些操作都被解决。您的 submitToOthers() 函数将返回一组承诺:

return this.idx.map((_entry, i) => {
    return updateGeneralInfoToOther(1, data, this.serverFullAddress[i]).then((res) => {
        if (res.status == 200) {
            this.serverResCheck[i] = true
        } else {
            this.serverResCheck[i] = false
        }
    })
});

那么,只需使用Promise.all() 等待这个promise数组被解析:

async submitTotalServer() {
    await Promise.all(this.submitToTheOthers());

    // Rest of the logic
    // ...
}

【讨论】:

    【解决方案2】:

    也许这就是你需要的 for await

     async function test() {
    let array=[1,2,3,4,5]
              for await (const elem of array) {
               
                 console.log(elem);
              }
           }
    

    【讨论】:

    • 你忘记了最后的{}
    【解决方案3】:

    通过标记函数async,您是在告诉它:如果遇到await,在等待的promise 返回(解决或拒绝)之前不要继续执行其余代码。但是在您的 submitToTheOthers 函数中,您根本没有使用 await,因此请求是一次性发出的,并且函数无需等待即可返回。

    虽然在每次调用前放置 await 可以解决您的问题,但在循环内部,每次迭代都会等待前一次完成,这肯定会比一次发送所有请求花费的时间要长得多.从您所展示的内容来看,它们似乎可以并行运行。

    为此,您可以使用 Promise.all(),它旨在并行处理多个单独的 Promise。以下应该可以工作,无需对您的代码进行任何其他更改:

    submitToTheOthers() {
      return Promise.all(
        this.idxs.map((_, i) => updateGeneralInfoToOther(
          1,
          { data: 'test' },
          this.serverFullAddress[i]
        ) 
          .then(r => { 
             this.serverResCheck[i] = r.status === 200;
             return r;
          })
          .catch(e => {
             this.serverResCheck[i] = false;
             return e;
          })
      ));
    }
    

    【讨论】:

      【解决方案4】:

      即使你标记了async submitToTheOthers,你实际上并没有让它表现得像一个异步函数。

      在该函数内部,我认为这是异步的这一行:updateGeneralInfoToOther(1, data, this.serverFullAddress[i]')。你循环调用这个函数,但问题是你没有await它,也没有返回promise。

      您需要将await 放在它前面,但这会使其等待每个处理循环中的下一个处理。另一种方法是将每个承诺存储在一个数组中,然后在函数末尾执行await Promise.all(promises)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-05-07
        • 1970-01-01
        • 1970-01-01
        • 2019-01-03
        • 2019-11-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多