如何等待包裹在 for 循环中的多个异步方法的结果?

How to wait for results from multiple async methods wrapped in a for loop?

我正在开发一种搜索算法,它可以搜索 3 个数据库并打印出结果。代码的一般结构如下所示:

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
}

那些 <type>_search_results_full 将是一个列表,其中包含 search_string 的完整匹配列表。然后我想等待所有这些列表被填充,然后 运行 通过另一种方法 getFinalDisplayResults 它们从这些完整列表中选择总共显示 X 个结果。

我面临的问题是 this.getFinalDisplayResults() 在那些 <type>_search_results_full 列表已满之前执行。我尝试将所有内容放在 for 循环中的单独方法 getFullResults() 中,然后执行如下操作:

async getFinalDisplayResults(){
  await getFullResults()
  // Do something
}

但这似乎不起作用,因为添加一些日志表明 getFullResults() 中的 for 循环在没有填充列表的情况下完成。

我对 toPromise() 和异步方法不是很了解,所以我确定我只是错误地处理了这个问题。有人可以帮助我了解我应该做什么吗?

我认为您正在寻找的是 Promise.all,因为它需要一组 Promise 并解析为一组结果。

以你的例子为例,它可能是这样的:

const results = await Promise.all(["player", "team", "event"].map( type => 
   this.searchService.getSearchResult(type).toPromise()
))

我们可以稍微清理一下,主要是迭代随类型数组变化的内容。

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

我想我知道你试图实现什么,以及你遇到的问题,this.getFinalDisplayResults() 在你得到结果之前执行,因为 for 循环内的逻辑是异步的,所以修复是。

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
}