如何使用foreach循环在其他异步调用中进行异步调用

时间:2020-03-19 07:29:47

标签: javascript angular typescript asynchronous

我真的很想改进并了解如何做得更好。该代码有效,但是我相信这里有问题。这个想法如下:

1:我对API进行了首次HTTP调用,并获得了数据。

2:我使用的数据是matchHistoryArr,该数组具有10个“ gameIds”数组,我需要将它们通过forEach(loop)传递给this.summ.getMatches(gameId)并将其推送到所需的新本地数组与另一个数组进行排序(因为异步未对其进行排序),因此在进行大量搜索之后,我可以像这样解决它。 (我将在代码中标记) 注意:这是我遇到大问题的地方,

3:现在我需要从其他端点获取更多数据,但是我认为在继续之前必须更好地排序代码。

Component.ts

     onSubmit(){
** 1 **
    this.summ.getSummoner(this.summoner.name,this.summoner.regionId)
    .subscribe(  (data:any) => {

      let matchHistoryArr = data.matchHistory

      let gameIdArray = matchHistoryArr.map( element => element.gameId)

      const subscribers: Subscriber<any>[] = [];
        const promiseMatchesArray = [];

** 2 **
       matchHistoryArr.forEach( element => {

         promiseMatchesArray.push( this.summ.getMatches(element.gameId).toPromise().then( match => {

           subscribers.push(match)
         }));
         });

           Promise.all(promiseMatchesArray).then( a =>{
               if ( subscribers.length === matchHistoryArr.length ){

                let arraySort = [];
                arraySort = subscribers
                let dataParticipants

                  let matchesArraySorted = arraySort.sort((a, b) => {  
                   return gameIdArray.indexOf(a.gameId) - gameIdArray.indexOf(b.gameId);
                 });

                 this.matchesArray = matchesArraySorted

                 matchesArraySorted.forEach( x => {

                  dataParticipants = x.participants
                  });

                  if ( dataParticipants.length === 10 ){

                    this.dataParticipants = dataParticipants
                  }
               }
           });


      this.matchHistory = matchHistoryArr
      this.SummInfo = data.summonerdata;

     });

  }

Services.ts

export class SummonerService {

  constructor( private http:HttpClient ) { }

  summonerName

    getSummoner(summonerName,regionId){
    this.summonerName = summonerName
   return this.http.get(`http://localhost:3000/summName/${summonerName}/${regionId}` )
   .pipe(
    map( (data:any) => data)
   )};



   getChampImage(champId){
     return this.http.get(`https://raw.communitydragon.org/latest/plugins/rcp-be-lol-game-data/global/default/v1/champion-icons/${champId}.png`)
   };

   getMatches(gameId){
     return this.http.get( `http://localhost:3000/match/${gameId}` )
     .pipe( 
       map( (data:any) => this.uploadData(data))
       )};

1 个答案:

答案 0 :(得分:0)

本质上,您的示例可以归结为两个步骤:

  1. 从可观察的数据中获取数据
  2. 根据来自1的数据执行一组呼叫。

除非有充分的理由使用诺言,否则我建议始终坚持观察到的事物。

  1. 在进行通话时进行初始通话 1a。使用concatMap
  2. 切换到新的观测值
  3. 创建可观察变量数组,并使用forkJoin并行运行
onSubmit() {
  this.summ.getSummoner(this.summoner.name, this.summoner.regionId)
    .pipe(
      tap((summoner) => this.matchHistory = summoner.matchHistory),
      concatMap((summoner: any) => {
        const observables = this.matchHistory
          .map(element => this.summ.getMatches(element.gameId));
        return forkJoin(observables)
      }),
      map(matchesArray => {
        // TODO: perform sorting
        return matchesArray;
      })
    ).subscribe(matchesArray => {

    });
}

为了简化答案,我已经省略了您的排序。

matchesArray是反映输入observables的结果数组。

任何要执行的排序都可以在map运算符中进行。

任何要保存到管道外的状态都可以在tap运算符中完成。

合并可观察变量的关键是要记住只有一个顶级订户。您几乎可以想到使用管道运算符的任何方式来组合可观察变量。这就是为什么我建议坚持观察到的原因。在复杂的场景中,它们比承诺更强大。