Angular 等待可观测在可观测范围内完成
我有以下数据结构:Angular 等待可观测在可观测范围内完成,angular,typescript,observable,Angular,Typescript,Observable,我有以下数据结构: export class Repo { id: number; name: string; contributors: Contributor[]; } export class Contributor { id: number; login: string; } 我正在使用Observable获取所有回购数据,但我想在外部repo被认为完全发出之前,在内部调用另一个ObservableObservable来填充所有参与者。我不知道
export class Repo {
id: number;
name: string;
contributors: Contributor[];
}
export class Contributor {
id: number;
login: string;
}
我正在使用Observable
获取所有回购数据,但我想在外部repo
被认为完全发出之前,在内部调用另一个ObservableObservable
来填充所有参与者。我不知道该怎么做。我有以下代码
private repos: Repo[] = [];
getRepos(orgName: string): void {
const repoBuild: Repo[] = [];
this.githubService.getRepos(orgName).pipe(
// this here won't wait for all contributors to be resolved
map(repo => this.getRepoContributors(orgName, repo))
).subscribe(
repo => repoBuild.push(repo),
error => {
this.repos = [];
console.log(error);
},
() => this.repos = repoBuild
);
}
// fetches contributors data for the repo
private getRepoContributors(orgName: string, repo: Repo): Repo {
const contributors: Contributor[] = [];
repo.contributors = contributors;
this.githubService.getRepoContributors(orgName, repo.name)
.subscribe(
contributor => {
// add to the total collection of contributors for this repo
contributors.push(contributor);
},
error => console.log(error),
() => repo.contributors = contributors
);
return repo;
}
我承认我对可观测的的理解是有限的,我为此奋斗了好几个小时。我试图在StackOverflow上找到适合我的东西,但仍然找不到有效的解决方案。任何帮助都将不胜感激
(代码是用角5写的)
解决方案:
我在下面使用了@joh04667建议,并最终使其生效。我是这样做的:
getRepos(orgName: string): void {
const repoBuild: Repo[] = [];
this.githubService.getRepos(orgName).pipe(
// mergeMap() replaces `repo` with the result of the observable from `getRepoContributors`
mergeMap(repo => this.getRepoContributors(orgName, repo))
).subscribe(
repo => repoBuild.push(repo),
error => {
this.repos = [];
console.log(error);
},
() => this.repos = repoBuild
);
}
// fetches contributors data for the repo
private getRepoContributors(orgName: string, repo: Repo): Observable<Repo> {
repo.contributors = []; // make sure each repo has an empty array of contributors
return this.githubService.getRepoContributors(orgName, repo.name).pipe(
// tap() allows us to peek on each contributor and add them to the array of contributors
tap(contributor => {
// add to the total collection of contributors for this repo
repo.contributors.push(contributor);
}),
// only picks the last contributor and replaces him/her with the repo
last(
() => false,
() => repo,
repo
)
);
}
getRepos(组织名称:字符串):无效{
常量repoBuild:Repo[]=[];
这个.githubService.getRepos(orgName).pipe(
//mergeMap()将“repo”替换为“getrepo”的可观察结果`
mergeMap(repo=>this.getRepoContributors(orgName,repo))
).订阅(
repo=>repoBuild.push(repo),
错误=>{
本公司回购利率=[];
console.log(错误);
},
()=>this.repos=repoBuild
);
}
//获取回购协议的参与者数据
私有getRepoContributors(orgName:string,repo:repo):可观察{
repo.contributors=[];//确保每个repo都有一个空的参与者数组
返回这个.githubService.getRepoContributors(orgName,repo.name).pipe(
//tap()允许我们查看每个贡献者并将其添加到贡献者数组中
点击(参与者=>{
//添加到此回购协议的供款人总集合中
回购贡献者推送(贡献者);
}),
//仅选择最后一位供款人,并用回购协议替换他/她
最后(
()=>错,
()=>回购,
回购
)
);
}
在最后一部分中,我使用了
last()
我基本上告诉了可观察的
,即使它会处理所有的值,我也只会使用最后一个值。最后一个类型是Contributor
,但我用一个默认值(即repo
)替换它,它允许我将返回类型从Observable
更改为Observable
,这正是我需要更高级别的Observable,对我来说,这是真正理解可观察物的全部力量的“大步”:高阶可观察物,或返回可观察物的可观察物
您的情况非常适合操作员:
getRepos(orgName: string): void {
const repoBuild: Repo[] = [];
this.githubService.getRepos(orgName).pipe(
// this will map the emissions of getRepos to getRepoContributors and return a single flattened Observable
mergeMap(repo => this.getRepoContributors(orgName, repo))
).subscribe(
repo => repoBuild.push(repo),
error => {
this.repos = [];
console.log(error);
},
() => this.repos = repoBuild
);
}
mergeMap
将外部可观察对象的发射映射到内部可观察对象(getRepos
),并返回仅在内部可观察对象完成时发射的新可观察对象。换言之,它将从一个可观测值传递到另一个可观测值的值展平到一个简洁的可订阅数据流中
高阶观测值很难让你头脑清醒,但这才是观测值真正的力量所在。我强烈建议在我链接的站点上查看其他一些操作符,如switchMap
和concatMap
。当使用到最大程度时,可观察物会变得异常强大
编辑
我误读了原始代码,认为getRepoContributors
返回了一个可观察的。漫长的工作日把我累坏了。我将在这里重构:
map
用于在与mergeMap
合并之前更改值。可以在那里完成getRepoContributors
的前几行。由于mergeMap
需要返回一个可观察的对象,我们可以稍微简化一下:
private repos: Repo[] = [];
getRepos(orgName: string): void {
const repoBuild: Repo[] = [];
this.githubService.getRepos(orgName).pipe(
map(repo => {
repo.contributors = [];
return repo;
}),
mergeMap(repo => this.githubService.getRepoContributors(orgName, repo.name)),
map(contributor => {
repo.contributors.push(contributor)
})
).subscribe(
repo => repoBuild.push(repo),
error => {
this.repos = [];
console.log(error);
},
() => this.repos = repoBuild
);
}
// don't need second function anymore
我们可以在流中
映射
,期望值按顺序与运算符一起更改。您是否尝试过使用switchmap或flatmap运算符Hey@joh04667谢谢您的回答,但我无法让它工作。这就是我的问题:我需要发出一个repo
,这样我就可以将它传递给getrepoaccomponents
,在那里它使用repo.name
来获取贡献者,然后我订阅getrepoamporters
,以收集数组中的所有参与者,订阅完成后,我将这些参与者分配回repo
。使用mergeMap
的这种方法会将我的Observable
转换为Observable
,因此当我订阅时,我不再有权获得回购。啊,明白了。没有看到您在第二个方法中订阅了另一个可观察对象,而不是返回一个可观察对象。我会更新我的答案。