【问题标题】:Wait for loop to finish before executing next line在执行下一行之前等待循环完成
【发布时间】:2019-08-28 22:39:12
【问题描述】:

我正在使用 GitHub API 检索存储库列表,然后遍历每个存储库并发出另一个 HTTP 请求以检索最新的提交日期。如何让它在创建loading = false 之前执行循环以找到最新的提交日期,以便我可以在页面上显示结果?

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

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

【问题讨论】:

    标签: javascript jquery angular


    【解决方案1】:

    在 for 后面插入 this.loading = false;。不是在 api 调用之后

    【讨论】:

    • 这将不起作用,因为 this.API.getCommits 是异步的。我们需要等待它“解决”,然后加载可能是错误的。
    • Júlio 和 @Ash,您可以使用 'rxjs' 运算符“tap”:pipe(tap(()=>this.loading=false)
    • 您不应该这样做,因为这会在填充 repos 之前将 loading 设置为 false。
    【解决方案2】:

    forkJoin 是你的朋友。它可以接受一个可观察的数组并将结果解析为一个数组。

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

    那么发生了什么?

    1. 我们得到了回购
    2. 我们使用 switchMap 获取结果并将其转换为另一个 observable
    3. 我们使用 forkJoin 将 repos 数组转换为可解析为单个 observable 的 observable 数组
    4. 我们使用 map 将最后一次提交添加到我们的 repo 对象并返回 new repo 对象。

    作为旁注...

    使用管道转换您的数据。订阅应用于消费转换的管道。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-15
      • 2019-12-31
      • 2020-04-29
      • 2014-07-30
      • 2021-01-03
      • 2021-07-30
      • 1970-01-01
      • 2017-05-10
      相关资源
      最近更新 更多