¿Por qué todas mis llamadas a funciones se ejecutan en paralelo aquí cuando uso await? ¿Qué se necesita cambiar para iniciar una llamada de función una vez hecho lo anterior?
for (let collection of collections) { await this.updateListings(collection) } private async updateListings(collection: Collection) { try { const startTime = Date.now(); const supply = collection.stats.total_supply; const contract_address = collection.primary_asset_contracts[0].address; const token_ids = []; for (let i = 1; i <= supply; i++) { token_ids.push(i); } let offset = 0; let limit = 30; while (offset + limit <= supply) { this.apiKey = this.apiKeys.find(key => key !== this.apiKey); //rotate api key on each request const ids = token_ids.splice(0, 30); const params = new URLSearchParams(); params.set("offset", offset.toString()); params.set("limit", limit.toString()); params.set("side", "1"); params.set("sale_kind", "0"); params.set("order_by", "eth_price"); params.set("order_direction", "asc"); params.set("asset_contract_address", contract_address); for (let i = 0; i < ids.length; i++) { params.append("token_ids", ids[i]) } await this.delayRequest(700); const response = await axios.get(process.env.OPENSEA_API_BASE_URL + "/orders", { headers: { "X-API-KEY": this.apiKey, 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36' }, params: params }) const { orders } = response.data; if (orders.length > 0) await getRepository(Listing).save(orders); offset += limit; console.log(`update listings for ${collection.slug} status: ${offset} / ${supply}`) } const endTime = Date.now() - startTime; console.log("fetched listings for " + collection.slug + " in " + endTime + " ms") } catch (error) { console.log("updating listings for " + collection.slug + " failed", error.message); } } constructor() { setTimeout(() => { this.update(); }, 6000) }Lo que espero es que la primera iteración finalice antes de que continúe, pero está llamando a cada iteración "updateListings (coll)" al mismo tiempo.
En realidad. su código se ejecuta secuencialmente. ¿Cómo comprobó que su código se estaba ejecutando en paralelo?
Puedes usar Array.reduce para hacerlo secuencialmente:
return collections.reduce((currentPromiseChain, collection) => { return currentPromiseChain.then(() => this.updateListings(collection)); }, Promise.resolve());Simplemente agregue una espera antes de la condición. Esto asegurará que cada bucle finalice antes de continuar con el siguiente.
Nota: no estoy completamente seguro de la compatibilidad para esto, es posible que deba verificar la compatibilidad.
for await (let collection of collections) { //notice the await in this line. await this.updateListings(collection) }Esto es para demostrar que no hay nada de malo en la forma en que está llamando for loop , y también en cómo tiene un while loop dentro de su función updateListing .
¿Probablemente hay algo que no mostraste?
La única razón que puedo ver, que afecta sus códigos, es si hay errores, y su bloque try/catch devuelve la promesa con error inmediatamente, haciendo que parezca que se está ejecutando en paralelo.
const whileLoopFunction = async(value) => { let limit = 0; let supply = 10 while (limit < supply) { await new Promise(resolve => setTimeout(resolve,100)) limit++ } console.log('While loop complete for value ', value) }; (async() => { const collections = [ 1, 2, 3, 4, 5 ] console.log("For loop works with await") for (let collection of collections) { await whileLoopFunction(collection) } })()