【发布时间】:2020-03-05 13:18:37
【问题描述】:
我试图在我的解析器中返回一堆嵌套的 forkjoins 和正常订阅。为此,我尝试使用地图,但我认为我还没有完全掌握地图/switchMaps/mergeMaps 的概念。 我知道代码还没有返回 UserResult,这是因为我还不知道如何将 questionAnswers 添加到 UserResult,但这对我当前的问题应该没有太大的区别。
我的目标是重写它,使它返回一个可观察的对象。
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<UserResult> {
const questionAnswers = Array<QuestionAnswer>();
this.rs.getResult(this.auth.token, route.params['id']).subscribe(res => {
forkJoin(
this.quizs.getCategoriesQuiz(this.auth.token, res.quizId),
this.accs.getAccount(res.userId)
).subscribe(results => {
forkJoin(
this.accs.getUserDetails(results[1].access_token),
this.as.getAnswers(this.auth.token)
).subscribe(results2 => {
results[0].forEach(cat => {
this.cs
.getQuestionsCategory(this.auth.token, cat.id)
.subscribe(questions => {
results2[1]
.filter(ans => ans.userId === results[1].uid)
.forEach(a => {
const question = questions.find(q => q.id === a.questionId);
if (!isNullOrUndefined(question)) {
const category = results[0].find(
c => c.id === a.categoryId
);
const qa = new QuestionAnswer(question, a);
qa.category = category.name;
questionAnswers.push(qa);
}
});
});
});
});
});
});
}
我尝试像这样重写它,但它根本不起作用。我收到了一些未定义的错误,但它们都指向管道的开头,没有具体的。
const questionAnswers = Array<QuestionAnswer>();
let res;
let res2;
return this.rs.getResult(this.auth.token, route.params['id']).pipe(
map((res: Result) =>
forkJoin(
this.quizs.getCategoriesQuiz(this.auth.token, res.quizId),
this.accs.getAccount(res.userId)
)
),
tap(results => (res = results)),
map(results =>
forkJoin(
this.accs.getUserDetails(results[1].access_token),
this.as.getAnswers(this.auth.token)
)
),
tap(results2 => (res2 = results2)),
map(
res[0]
.forEach(cat => {
this.cs.getQuestionsCategory(this.auth.token, cat.id);
})
.map(questions =>
res2[1]
.filter(ans => ans.userId === res[1].uid)
.forEach(a => {
const question = questions.find(q => q.id === a.questionId);
if (!isNullOrUndefined(question)) {
const category = res[0].find(c => c.id === a.categoryId);
const qa = new QuestionAnswer(question, a);
qa.category = category.name;
questionAnswers.push(qa);
}
})
)
)
);
编辑
我刚刚注意到,在点击 results2 后 res[0] 会导致
无法读取未定义的属性“0”
我认为这与我对水龙头的使用不当有关,因为它在我试图更改的订阅中运行良好。
EDIT2
我像 Kurt 推荐的那样将代码拆分为更小的函数,但是我不太确定如何将它与我用于类别的 forEach 一起使用。我也不知道应该在哪里创建我将作为可观察对象返回的最终对象
getResultByRouteParamId(route: ActivatedRouteSnapshot): Observable<Result> {
return this.rs.getResult(this.auth.token, route.params['id']);
}
forkJoinQuizCategoriesAndAccount(
result: Result
): Observable<[Category[], Account]> {
return forkJoin(
this.quizs.getCategoriesQuiz(this.auth.token, result.quizId),
this.accs.getAccount(result.userId)
);
}
forkJoinUserDetailsAndAnswers(results: [Category[], Account]) {
return forkJoin(
this.accs.getUserDetails(results[1].access_token),
this.as.getAnswers(this.auth.token)
);
}
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<UserResult> {
const questionAnswers = Array<QuestionAnswer>();
let result: Result;
let res: [Category[], Account];
let res2: [User, Answer[]];
return this.getResultByRouteParamId(route).pipe(
tap(resu => result = resu),
switchMap((result: Result) => this.forkJoinQuizCategoriesAndAccount(result)),
tap(results => (res = results)),
switchMap(results => this.forkJoinUserDetailsAndAnswers(results)),
tap(results2 => (res2 = results2)),
switchMap(
// Stuck here!
res[0]
.forEach(cat => {
this.cs.getQuestionsCategory(this.auth.token, cat.id);
})
.map(questions =>
res2[1]
.filter(ans => ans.userId === res[1].uid)
.forEach(a => {
const question = questions.find(
(q: Question) => q.id === a.questionId
);
if (!isNullOrUndefined(question)) {
const category = res[0].find(
(c: Category) => c.id === a.categoryId
);
const qa = new QuestionAnswer(question, a);
qa.category = category.name;
questionAnswers.push(qa);
}
}
// let ur = new UserResult(res2[1], result)
// ur.questionAnswers = questionAnswers;
// return ur;
)
)
)
);
【问题讨论】:
-
Kurt 在下面的回答太棒了,只是想补充一下,你出错的主要原因是
.pipe(map(x => forkJoin([...])), ...)几乎总是错误的并且是反模式。这里x是可观察对象的内部,通常是一个普通对象,并且您映射到forkJoin可观察对象而不是另一个对象。正如 Kurt 所说,更喜欢.pipe(switchMap(x => forkJoin([...])), ...)或.pipe(concatMap(x => forkJoin([...])), ...)
标签: angular rxjs observable