Итак ... это большая часть Rx JS, которую вы получили.
Перво-наперво - вы не подписываетесь внутри операторов Rx JS - вы объединяете наблюдаемые вместе.
Некоторые определения
switchMap
и concatMap
используются для передачи результатов одного наблюдаемого другому.
map
предназначен для преобразования значения из одной структуры в другую (аналогично концепции функции массива с тем же именем).
forkJoin
объединяет несколько наблюдаемых и возвращает один результат когда все они завершатся.
Ваш код
Прежде чем вы даже начнете пытаться исправить свой код, я бы рекомендовал подумать о разделении каждого шага на его собственную функцию. Надеюсь, это поможет вам увидеть поток данных и подумать о том, где находятся ваши зависимости.
У меня было go при преобразовании вашего исходного примера в Rx JS, но я немного растерялся, думая о что каждый шаг на самом деле пытался достичь.
Что я сделал, так это то, что вы получите шаблон, похожий на этот (я подписываюсь для целей этой демонстрации - вы бы вернули наблюдаемое):
result: string;
ngOnInit() {
this.initialValue().pipe(
switchMap(result => this.forkJoinOne(result)),
switchMap(result => this.forkJoinTwo(result)),
switchMap(result => this.forkJoinThree(result)),
map(result => this.mapFour(result))
).subscribe(result => {
this.result = result;
});
}
private initialValue(): Observable<string> {
return of('zero');
}
private forkJoinOne(result: string): Observable<string[]> {
return forkJoin([
of(`${result} one`),
of('four')
]);
}
private forkJoinTwo(results: string[]): Observable<string[]> {
return forkJoin([
of(`${results[0]} two`),
of(`${results[1]} five`)
]);
}
private forkJoinThree(results: string[]): Observable<string[]> {
return forkJoin([
of(`${results[0]} three`),
of(`${results[1]} six`)
]);
}
private mapFour(results: string[]): string {
return results.join(' ');
}
Каждый наблюдаемый шаг перенесен в свою собственную функцию - это помогает вам думать о том, какие данные должны поступать, а какие выходить - вы фактически создаете контракт между каждым шагом.
switchMap
просто берет одну наблюдаемую и настраивает другую. В итоге map
берет вывод предыдущей наблюдаемой и преобразует его в другое значение.
Я использовал здесь строки, чтобы, надеюсь, упростить отслеживание потока данных. Я бы порекомендовал начать с попытки понять мой простой пример, а затем перестроить вашу функцию, используя принципы.
DEMO: https://stackblitz.com/edit/angular-eedbqg
Моя версия примерно выравнивается с вашими следующими способами:
initialValue
this.rs.getResult(this.auth.token, route.params['id'])
forkJoinOne
All fork объединения должны передавать в массив или объект. Я предпочитаю относительно новый способ передачи объектов, который определяет структуру излучаемой стоимости. (forkJoin({ a: myObs })
возвращает { a: value }
).
forkJoin(
this.quizs.getCategoriesQuiz(this.auth.token, res.quizId),
this.accs.getAccount(res.userId)
)
forkJoinTwo
forkJoin(
this.accs.getUserDetails(results[1].access_token),
this.as.getAnswers(this.auth.token)
)
forkJoinThree
Вы будете необходимо преобразовать этот l oop в массив наблюдаемых и передать его в forkJoin
.
results[0].forEach(cat => {
this.cs.getQuestionsCategory(this.auth.token, cat.id)
mapFour
Вам потребуется разбери свою карту. Вместо forEach
здесь предпочтительнее filter
и map
(функция массива).
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);
}
})