简体   繁体   English

等待循环完成,然后再执行下一行

[英]Wait for loop to finish before executing next line

I am using the GitHub API to retrieve a list of repos and afterwards looping over each repo and making another HTTP request to retrieve the latest commit date. 我正在使用GitHub API检索存储库列表,然后遍历每个存储库,并发出另一个HTTP请求以获取最新的提交日期。 How can I have it execute the loop to find the latest commit date before making loading = false so I can show the results on the page? 我如何在执行loading = false之前执行循环以查找最新的提交日期,以便在页面上显示结果?

API.service.ts API.service.ts

export class APIService {

  constructor(private http: HttpClient) { }

  getRepos(): Observable<any[]> 
    return this.http.get<any[]>('https://api.github.com/users/githubtraining/repos')
      .pipe(catchError(this.handleError));
  }

  getCommits(url: string): Observable<any> {
    return this.http.get<any>(url)
      .pipe(catchError(this.handleError));
  }

  handleError(error: any) {
    return throwError(error);
  }

}

dashboard.component.ts dashboard.component.ts

export class DashboardComponent implements OnInit {

  repos: Repo[];
  loading = true;

  constructor(private API: APIService) { }

  ngOnInit() {
    this.getAllRepos();
  }

  getAllRepos() {
    this.API.getRepos().subscribe(data => {
      this.repos = data;
      for (const repo of this.repos)
      {
        const commit_url = repo.branches_url.replace('{/branch}', `/${repo.default_branch}`);
        this.API.getCommits(commit_url).subscribe(commit => {
          repo.last_commit_date = commit.commit.commit.author.date;
        });
      }
    });
    // Finish looping over all repos before loading is false
    this.loading = false;
  }
}

Insert this.loading = false; 插入this.loading = false; after the for. 之后的。 Not after the api call 不是在api调用之后

forkJoin is your friend here. forkJoin是您的朋友在这里。 it can take an array of observables and resolve the results into an array. 它可以采用一个可观察对象数组并将结果解析为一个数组。

  getAllRepos() {
    this.API.getRepos()
        .pipe(switchMap((repos) => {
             return forkJoin(repos.map(repo => {
                const commit_url = repo.branches_url.replace('{/branch}', `/${repo.default_branch}`);

                return this.API.getCommits(commit_url)
                    .pipe(map(commit => {
                        repo.last_commit_date = commit.commit.commit.author.date;
                        return repo;
                    });
             })
        })
        .subscribe(repos => {
            this.repos = repos;
            this.loading = false;
        });
}

So whats happening? 那是怎么回事?

  1. We get the repos 我们得到了回购
  2. We use switchMap to take the result and transform it into another observable 我们使用switchMap获取结果并将其转换为另一个可观察的结果
  3. We use forkJoin to turn the array of repos, into an array of observables that resolve into a single observable 我们使用forkJoin将存储库数组转换为可观察变量数组,将其分解为单个可观察变量
  4. We use map to add the last commit to our repo object and return the new repo object. 我们使用map将最后一次提交添加到我们的repo对象中,并返回新的 repo对象。

As a sidenote... 作为旁注...

Use pipes to transform your data. 使用管道来转换数据。 Subscriptions should be for consumption . 订阅应用于消费 Pipes for transformation . 转换管道。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM