【问题标题】:How to make an async call inside other async call with a foreach loop如何使用 foreach 循环在其他异步调用中进行异步调用
【发布时间】:2020-03-19 07:29:47
【问题描述】:

我真的很想改进并了解如何更好地做到这一点。这段代码有效,但我相信这里有问题。思路如下:

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

【问题讨论】:

    标签: javascript angular typescript asynchronous


    【解决方案1】:

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

    1. 从 observable 中获取数据
    2. 根据来自 1 的数据执行一组调用。

    我建议始终坚持使用 observables,除非有令人信服的理由使用 Promise。

    1. 按照您的操作进行初始调用 1a。使用 concatMap 切换到新的 observable
    2. 创建 observables 数组并使用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 运算符中完成。

    组合可观察对象的关键是要记住只有一个顶级订阅者。 Observables 几乎可以用任何你能想到的使用管道操作符的方式组合起来。这就是为什么我建议坚持使用 observables。在复杂场景中,它们比 Promise 更强大。

    【讨论】:

    • 我非常感谢您的回复。现在我了解了如何使用一些 rxjs 运算符!现在,如果我想进行另一个端点调用并将该数据放入 matchesArray 中,我是否必须将其放入 map(matchesArray => { // 这里返回 matchesArray; 我应该在服务中执行逻辑吗?
    • 如果你想进行单个 observable 调用,请使用另一个 concatMap 来运行 observable。您可以使用.pipe(concatMap(obs1), concatMap(obs2), concatMap(obs3), ... ) 链链接任意数量的顺序调用。如果您想并行运行它们,请使用forkJoinconcatMap(() =&gt; forkJoin([obs1, obs2, obs3])
    • 再次感谢您! :)
    猜你喜欢
    • 2013-09-27
    • 1970-01-01
    • 2019-01-29
    • 1970-01-01
    • 2018-08-22
    • 1970-01-01
    • 2019-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多