Home > Blockchain >  How to use async/ await for a 'for statement' only
How to use async/ await for a 'for statement' only

Time:11-22

I want to use async function 'submitToTheOthers' and I want from let items = [] it will run after 'submitToTheOthers' is done. But it didn't wait until 'submitToTheOthers' is done. Probably it is because no await in 'submitToTheOthers'. Therefore, I want to make for statement in 'submitToTheOthers' as await like, but I don't know how.

I could use await at 'updateGeneralInfoToOther', but then I couldn't run updateGeneralInfoToOther for all servers at the almost same time, and if one of server has a error then I couldn't run from the server in the for statement. I want use await or promise like something for statement or little larger range.

What will be good way to make it wait 'submitToTheOthers'?

ps)I hope get to know older syntax because I likely need to use it on 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)
}
// ...

CodePudding user response:

Even though you've marked async submitToTheOthers, you aren't actually making it behave like an async function.

Inside that function, I assume it's this line that's async: updateGeneralInfoToOther(1, data, this.serverFullAddress[i]'). You call this function in a loop, but the problem is that you don't await it, nor do you return the promise.

You'll need to put await in front of it, but that will make it wait for each one to process the next one in the loop. The alternative is storing each promise in an array and then doing await Promise.all(promises) at the end of the function.

CodePudding user response:

maybe this is what u need for await

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

CodePudding user response:

The crux of the problem is that your for loop is not awaiting for the promise returned by updateGeneralInfoToOther() to resolve. To get your code to work, it is a quick fix of forcing the loop to await, i.e.:

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
        }
    })
}

However, this solution is not ideal, in the sense that you have to await each request individually: there is really no reason to do that. A better solution will be to simply perform all these async operations together, and then wait for all of them to be resolved. Your submitToOthers() function will return instead an array of promises:

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
        }
    })
});

Then, it is just a matter of using Promise.all() to wait for this array of promises to be resolved:

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

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

CodePudding user response:

By marking a function async you're telling it: if you run into an await, do not proceed to rest of code until the awaited promise has returned (resolved or rejected). But inside your submitToTheOthers function, you're not using await at all, so the requests are made all at once and the function returns without waiting for them.

Although placing an await in front of each call would solve your problem, inside the loop, each iteration would wait for the previous one to finish, which will surely take a lot longer than if you sent all the requests at once. From what you've shown, it looks like they could be run in parallel.

For this, you could use Promise.all() which is designed to handle multiple separate promises in parallel. The following should work, without the need to make any other change to your code:

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;
      })
  ));
}

CodePudding user response:

async function sample () {
 const data = await doSth();

for (const data of datas) {
 const contents = await YOUR_FUNCTION
 console.log();
}} 
  • Related