Estoy desarrollando un algoritmo de búsqueda que busca en 3 bases de datos e imprime los resultados. La estructura general del código se parece a esto:
for(type in ["player", "team", "event"]){ this.searchService.getSearchResult(type).toPromise() .then(search_result => { if(type == "player"){ this.player_search_results_full = this.getPlayerSearchResults(search_result, search_string); } if(type == "team"){ this.team_search_results_full = this.getTeamSearchResults(search_result, search_string); } if(type == "event"){ this.event_search_results_full = this.getEventSearchResults(search_result, search_string); } }) } // this.getFinalDisplayResults() getFinalDisplayResults(){ // Do some actions on <type>_search_results_full lists }
Esos <type>_search_results_full
serán una lista que contiene la lista completa de coincidencias para search_string. Luego, me gustaría esperar a que se completen todas esas listas, luego ejecutarlas a través de otro método getFinalDisplayResults
que elige un total de X resultados para mostrar de esas listas completas.
El problema al que me enfrento es que this.getFinalDisplayResults()
se ejecuta antes de que esas listas <type>_search_results_full
estén llenas. Intenté poner todo en el bucle for en un método separado getFullResults()
y luego hacer algo como esto:
async getFinalDisplayResults(){ await getFullResults() // Do something }
Pero eso parece no funcionar, ya que agregar algunos registros muestra que el ciclo for en getFullResults() finaliza sin que se llenen las listas.
No tengo una gran comprensión de toPromise() y los métodos asincrónicos, así que estoy seguro de que me estoy acercando a esto incorrectamente. ¿Puede alguien ayudarme a entender qué debería hacer en su lugar?
Creo que sé lo que intenta lograr y el problema que tiene, this.getFinalDisplayResults()
se ejecuta antes de que tenga los resultados porque la lógica dentro del bucle for es asíncrona, por lo que la solución sería.
async function getDataFromBackend () { for(let type in ["player", "team", "event"]) { const searchResult = await this.searchService.getSearchResult(type).toPromise() if(type === "player") this.player_search_results_full = this.getPlayerSearchResults(searchResult, search_string); if(type === "team") this.team_search_results_full = this.getTeamSearchResults(searchResult, search_string); if(type === "event") this.event_search_results_full = this.getEventSearchResults(searchResult, search_string); } } async function getFinalDisplayResults() { await getDataFromBackend(); // this will ensure you have the data, before you do the rest of the process //rest of the logic here }
Creo que lo que está buscando es Promise.all
, ya que toma una serie de Promise y se resuelve en una serie de resultados.
Con tu ejemplo, podría ser algo como:
const results = await Promise.all(["player", "team", "event"].map( type => this.searchService.getSearchResult(type).toPromise() ))
Podemos limpiarlo un poco, principalmente al iterar las cosas que varían en la variedad de tipos.
const promises = [ { type: 'player', method: 'getPlayerSearchResults'}, { type: 'team', method: 'getTeamSearchResults'}, { type: 'event', method: 'getEventSearchResults'} ].map(obj => { return this.searchService.getSearchResult(obj.type).toPromise().then(search_result => { return this[obj.method].bind(this)(search_result, search_string); }) }); return Promise.all(promises);