You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular嵌套*ngFor触发无限循环问题(Github仓库查看器场景)

Angular + GitHub API:解决仓库语言列表无限循环与展示异常问题

问题根源

  1. 模板调用函数触发无限循环:在*ngFor中直接调用languagesUsed(repo.name),Angular的变更检测机制会在每次检测周期执行这个函数。每次调用都会发起新的HTTP请求,请求完成后修改全局变量langs又会触发变更检测,形成无限循环。
  2. 全局变量导致语言列表混乱:所有仓库共用同一个langs数组,每个仓库的语言请求返回后都会覆盖这个数组,最终所有仓库显示的都是最后一次请求的语言结果,无法独立展示各仓库的语言。

解决方案

1. 调整组件逻辑,为每个仓库绑定专属语言列表

修改Component.ts,移除全局langs数组,在获取仓库列表后,为每个仓库单独请求语言并存储到自身属性中:

export class UserComponentComponent implements OnInit {

  @Input() username:any;
  
  constructor(private githubUser:UserDataService) { }
  repos:Array<any> = [];
  avatar:any;
  name:String = '';
  location:String = '';
  bio:String = '';
  twitter:String = ''; 
  github:String = '';
  totalRecords = 0;
  page = 1;
  // 移除全局langs数组

  getUser(){
    this.githubUser.getData(this.username).subscribe((data)=>{
        this.avatar = data.avatar_url;
        this.name = data.name;
        this.location = data.location;
        this.bio = data.bio;
        this.twitter = `https://twitter.com/${data.twitter_username}`;
        this.github = `https://github.com/${data.login}`;
    })
  }

  getRepos(){
    this.githubUser.getRepositories(this.username).subscribe((repos)=>{
        this.repos = repos;
        this.totalRecords = repos?.length;
        
        // 为每个仓库请求语言并绑定到自身属性
        repos.forEach(repo => {
          this.githubUser.getLanguages(this.username, repo.name).subscribe(languages => {
            repo.languages = Array.from(Object.keys(languages));
          });
        });

        // 【可选优化】用forkJoin批量请求,减少订阅次数
        // import { forkJoin } from 'rxjs';
        // import { map } from 'rxjs/operators';
        // const languageRequests = repos.map(repo => 
        //   this.githubUser.getLanguages(this.username, repo.name).pipe(
        //     map(langs => ({ repo, langs: Array.from(Object.keys(langs)) }))
        //   )
        // );
        // forkJoin(languageRequests).subscribe(results => {
        //   results.forEach(item => item.repo.languages = item.langs);
        // });
    })
  }

  // 移除原languagesUsed函数

  ngOnInit(): void{
    this.getUser();
    this.getRepos();
  }
}

2. 修改模板,直接遍历仓库的专属语言列表

修改HTML模板,不再调用函数,直接访问每个仓库的languages属性,同时添加*ngIf避免未加载完成时的报错:

<div class="user-repos">
  <ul id="repos" *ngFor="let repo of repos | paginate:{ id:'listing_repos',itemsPerPage:10, currentPage:page, totalItems:totalRecords}">
    <li>
      <h4>{{ repo.name | uppercase}}</h4>
      <p>{{ repo.description }}</p>
      <ul *ngIf="repo.languages">
        <li *ngFor="let lang of repo.languages">{{lang}}</li>
      </ul>
    </li>
  </ul>
</div>

3. 额外优化建议

  • 添加加载状态:可以给每个仓库对象添加isLoading属性,在请求语言时显示加载提示,提升用户体验
  • 实现缓存机制:创建一个languageCache对象存储已请求过的仓库语言,避免分页切换时重复发起API请求

内容的提问来源于stack exchange,提问作者Manan Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 09:27:22