Quiero usar la función asíncrona 'submitToTheOthers' y quiero que desde let items = []
se ejecute después de que 'submitToTheOthers' haya terminado. Pero no esperó hasta que 'submitToTheOthers' haya terminado. Probablemente sea porque no espera en 'submitToTheOthers'. Por lo tanto, quiero hacer una declaración en 'submitToTheOthers' como en espera, pero no sé cómo.
Podría usar await en 'updateGeneralInfoToOther', pero luego no podría ejecutar updateGeneralInfoToOther para todos los servidores casi al mismo tiempo, y si uno de los servidores tiene un error, entonces no podría ejecutar desde el servidor en la instrucción for. Quiero usar esperar o prometer como algo para una declaración o un rango un poco más grande.
¿Cuál será una buena manera de hacer que espere 'submitToTheOthers'?
ps) Espero conocer la sintaxis más antigua porque es probable que necesite usarla en Internet Explorer XD XD TT
Configuración.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/configuraciones.js
// ... export function updateGeneralInfoToOther(id, data, serverAddress) { axios.defaults.timeout = 5000; data.serverAddress = serverAddress return axios.post(`/api/settings/generalToOther/${id}`, data) } // ...
tal vez esto es lo que necesitas para esperar
async function test() { let array=[1,2,3,4,5] for await (const elem of array) { console.log(elem); } }
El quid del problema es que su bucle for
no está esperando que se resuelva la promesa devuelta por updateGeneralInfoToOther()
. Para que su código funcione, es una solución rápida para forzar el ciclo a await
, es decir:
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 } }) }
Sin embargo, esta solución no es ideal , en el sentido de que debe esperar cada solicitud individualmente: realmente no hay razón para hacer eso. Una mejor solución será simplemente realizar todas estas operaciones asíncronas juntas y luego esperar a que se resuelvan todas. Su función de submitToOthers()
devolverá en su lugar una serie de promesas:
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 } }) });
Entonces, solo es cuestión de usar Promise.all()
para esperar a que se resuelva este conjunto de promesas:
async submitTotalServer() { await Promise.all(this.submitToTheOthers()); // Rest of the logic // ... }
Al marcar una función async
, le está diciendo: si se encuentra con una await
, no continúe con el resto del código hasta que la promesa esperada haya regresado (resuelta o rechazada). Pero dentro de su función submitToTheOthers
, no está usando await
en absoluto, por lo que las solicitudes se realizan todas a la vez y la función regresa sin esperarlas.
Si bien colocar un await
delante de cada llamada resolvería su problema, dentro del bucle, cada iteración esperaría a que finalice la anterior, lo que seguramente llevará mucho más tiempo que si enviara todas las solicitudes a la vez. Por lo que ha mostrado, parece que podrían ejecutarse en paralelo.
Para esto, puede usar Promise.all()
que está diseñado para manejar varias promesas separadas en paralelo. Lo siguiente debería funcionar, sin necesidad de realizar ningún otro cambio en su código:
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; }) )); }