У меня есть следующая структура данных:
export class Repo {
id: number;
name: string;
contributors: Contributor[];
}
export class Contributor {
id: number;
login: string;
}
Я использую Observable<Repo>
для извлечения всех данных репо, но я хочу внутренне вызвать другую наблюдаемую Observable<Contributor>
для заполнения всех участников, прежде чем внешний Repo
будет считаться полностью выделенным. Я не уверен, как это сделать. У меня есть следующий код.
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;
}
Я признаю, что мое понимание по Observable
ограничено, и я боролся с этим довольно много часов. Я пытался найти что-то, что работает для меня в 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
)
);
}
Здесь, в последней части, где я использую last()
, я в основном говорю Observable
, что, хотя он будет обрабатывать все значения, я собираюсь использовать только последнее. Последний тип имеет тип Contributor
, но я заменяю его значением по умолчанию (repo
), которое позволяет мне изменить тип возвращаемого значения с Observable<Contributor>
на Observable<Repo>
, что именно то, что мне нужно для более высокого уровня Наблюдаемое.