gpt4 book ai didi

angular - 完成for循环后如何完成订阅者?

转载 作者:行者123 更新时间:2023-12-04 11:49:55 25 4
gpt4 key购买 nike

如果您制作 GET请求到 https://api.github.com/users/benawad/repos您将获得用户 benawad 的所有存储库已。至少这是 API 端点预期返回的内容。问题是 GitHub 将存储库的数量限制为 30。
enter image description here
截至今天(14/08/2021),用户 benawad 246 个存储库 .
为了克服上面提到的问题,你应该发出一个 GET 请求,但有一些额外的参数...... GitHub 已经实现了它的 API 的分页。因此,您应该在 URL 中指定 您想检索和每页的存储库数量 .
我们的新 GET请求应该是这样的:
https://api.github.com/users/benawad/repos?page=1&per_page=1000
问题在于,GitHub 将每页的存储库数量限制为 100。所以我们的 GET请求返回 100 个 repos 而不是用户 benawad 的 246目前有。
enter image description here
在我的 Angular 服务中,我实现了以下代码以从所有页面检索所有存储库。

  public getUserRepos(user: string): Observable<RepositoryI[]> {
return new Observable((subscriber: Subscriber<RepositoryI[]>) => {
this.getUserData(user).subscribe((data: UserI) => {
//public_repos is the amt of repos the user has
const pages: number = Math.ceil(data.public_repos / 100);

for (let i = 1; i <= pages; i++) {
this.http
.get(
`https://api.github.com/users/${user}/repos?page=${i}&per_page=100`
)
.subscribe((data: RepositoryI[]) => {
subscriber.next(data);
});
}
});
});
}
在我的组件中,我订阅了以下内容:
  this.userService.getUserRepos(id).subscribe((repos)=>{
this.repositories.push(...repos);
})
问题这种方法是我无法控制 Observable 何时停止发出值。在我的组件中,当 Observable 为 时,我想触发一个函数完整 .
我尝试了以下方法:
  public getUserRepos(user: string): Observable<RepositoryI[]> {
return new Observable((subscriber: Subscriber<RepositoryI[]>) => {
this.getUserData(user).subscribe((data: UserI) => {
const pages: number = Math.ceil(data.public_repos / 100);

for (let i = 1; i <= pages; i++) {
this.http
.get(
`https://api.github.com/users/${user}/repos?page=${i}&per_page=100`
)
.subscribe((data: RepositoryI[]) => {
subscriber.next(data);
// If the for loop is complete -> complete the subscriber
if(pages == i) subscriber.complete();
});
}
});
});
}
在我的组件中,我执行以下操作:
  this.userService.getUserRepos(id).subscribe(
(repos) => {
this.repositories.push(...repos);
},
(err) => {
console.log(err);
},
() => {
// When the observable is complete:

console.log(this.repositories); // This only logs 46 repositores, it should log 246
// I want to trigger some function here
}
);
console.log()仅记录 46 个存储库。为什么会这样?也许我在获取所有 3 个页面之前完成了订阅者;但我调用 .complete()在订阅里面。我究竟做错了什么?提前致谢。

最佳答案

您可以使用 RxJS 运算符和函数通过一次订阅来实现,如下所示:

public getUserRepos(user: string): Observable<RepositoryI[]> {
// will return one observable that contains all the repos after concating them to each other:
return this.getUserData(user).pipe(
switchMap((data: UserI) => {
//public_repos is the amt of repos the user has
const pages: number = Math.ceil(data.public_repos / 100);

// forkJoin will emit the result as (RepositoryI[][]) once all the sub-observables are completed:
return forkJoin(
Array.from(new Array(pages)).map((_, page) =>
this.http.get<RepositoryI[]>(
`https://api.github.com/users/${user}/repos?page=${page + 1}&per_page=100`
)
)
).pipe(
// will reduce the RepositoryI[][] to be RepositoryI[] after concating them to each other:
map((res) =>
res.reduce((acc, value) => {
return acc.concat(value);
}, [])
)
);
})
);
}
然后在您的组件中,您可以订阅在获取所有存储库后将返回所有存储库的 observable:
  this.userService.getUserRepos(id).subscribe((repos) => {
this.repositories = repos;
// You can trigger the function that you need here...
});

关于angular - 完成for循环后如何完成订阅者?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68787826/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com