#angular #google-cloud-firestore #rxjs
#angular #google-cloud-firestore #rxjs
Вопрос:
Я новичок в angular, и мне нужно подняться на холм, прежде чем я пойму, что происходит, и работа с наблюдаемыми из Firestore ставит меня в тупик. Мне нужно поле ID из одного вызова службы, чтобы получить данные из следующих двух вызовов службы, избегая при этом страшного undefined. Как нам это сделать?
this.myMatch = this.route.snapshot.paramMap.get("createdMatchIdKey");
this.golfDataService.GetSelectedMatch(this.myMatch)
.subscribe(result => {
this.match = resu<
this.setupTable(this.match.matchCourseId);
this.golfDataService.GetSelectedGolfCourse(this.match.matchCourseId)
.subscribe(result => {
this.course = resu<
console.log(this.course);
})
this.golfDataService.GetSelectedCourseTees(this.match.matchCourseId)
.pipe(takeUntil(this.onDestroy))
.subscribe(result => {
this.tees = resu<
console.log(this.tees);
for (var i = 0; i < this.tees.length; i ) {
this.golfDataService.GetHoles(this.tees[i].teeIdKey)
.subscribe(result => {
console.log(this.teeHoleInfo);
this.teeHoleInfo.push(result);
console.log(this.match);
})
}
})
})
Ответ №1:
В общем, «способ» RxJS заключается в том, чтобы попытаться сохранить ваш конвейер как можно более чистым (без внешних побочных эффектов). Вы, конечно, можете использовать tap
для установки своих глобальных переменных по пути, но я думаю, что это лучше с точки зрения тестирования, модульности и расширения — возможности не делать ничего из этого, пока вы не получите все свои данные.
Этот подход создает объект вида:
{
match: any,
course: any,
tees: any[],
holes: any[]
}
- совпадение — это результат
golfDataService.GetSelectedMatch
- конечно, это результат
golfDataService.GetSelectedGolfCourse
- tees — это результат
golfDataService.GetSelectedCourseTees
- отверстия — это объединенный результат целого ряда вызовов
golfDataService.GetHoles
(golfDataService.GetHoles
для каждой записи в tees должен быть один вызов)
Конечный результат получает подписку, а затем там вызываются все консоли и присваивания вашим глобальным переменным.
this.myMatch = this.route.snapshot.paramMap.get("createdMatchIdKey");
this.golfDataService.GetSelectedMatch(this.myMatch).pipe(
mergeMap(match =>
zip(
this.golfDataService.GetSelectedGolfCourse(match.matchCourseId),
this.golfDataService.GetSelectedCourseTees(match.matchCourseId)
).pipe(
take(1),
map(([course, tees])=> ({
match,
course,
tees
}))
),
mergeMap(({match, course, tees}) =>
zip(
...tees.map(tee => this.golfDataService.GetHoles(tee.teeIdKey))
).pipe(
take(1),
map(holes => ({
match,
course,
tees,
holes
}))
)
)
)
).subscribe(({match, course, tees, holes}) => {
this.match = match;
this.setupTable(this.match.matchCourseId);
this.course = course;
console.log(this.course);
this.tees = tees;
console.log(this.tees);
this.teeHoleInfo = holes;
console.log(this.teeHoleInfo);
});
Следует отметить, что fork(...)
это, вероятно, лучше, чем zip(...).pipe(take(1))
, но работает только при запуске observable, который, как вы уверены, будет завершен.