He estado tratando de combinar varias llamadas asíncronas desde hace un tiempo, y cada vez que me acerco, me quedo atascado en un bucle foreach que estoy tratando de resolver.
En este momento, paso una matriz de categorías a una función, que devolverá un observable que contiene una matriz de todas las preguntas (de todas las categorías combinadas).
estaba pensando en
getQuestions(categories: Category[]): Observable<Question[]> { let q: Question[]; categories.forEach(c => { this.cs .getQuestionsCategory(c.id) .pipe(map(questions => q.push(...questions))); //return q somehow? }); }Entonces sería capaz de usarlo así:
let result: Result; let res: [Category[], Account, Answer[]]; return this.getResultByRouteParamId(route).pipe( tap(resu => (result = resu)), switchMap((result: Result) => this.forkJoinQuizCategoriesAccountAnswers(result) ), tap(results => (res = results)), switchMap(x => this.getQuestions(res[0])), map(questions => { // Create objects of questions, answers and category and add them to a QuestionAnswer object // Return new UserResult containing the user and a list of QuestionAnswer objects return new UserResult(null, null); }) );Esto es lo más cerca que pude llegar a la recomendación de alguien sobre mi pregunta anterior . Quería agregar esto a mi pregunta original, pero siento que esto no sería lo correcto, ya que ya no estoy luchando con observables anidados, sino con bucles sobre ellos.
EDITAR
Intenté algo más, pero dudo que esta sea la forma correcta de hacerlo.
getQuestions(categories: Category[]): Observable<Question[]> { let ques = categories.map(c => this.cs.getQuestionsCategory(this.auth.token, c.id) ); return merge(...ques); }Primero, me gusta la idea de poner esto en una función dedicada, para que puedas separar la interfaz de la implementación.
El problema que desea resolver debe ser factible en la tubería, es solo un caso de averiguar qué está sucediendo.
Category .Question .Me acercaría a esto por:
forkJoin la matriz observable. Por sí mismo, esto devolverá una matriz bidimensionalmap la matriz bidimensional a una matriz plana getQuestions(categories: Category[]): Observable<Question[]> { // firstly, start out with an array of observable arrays const observables: Observable<Question[]>[] = categories.map(cat => this.cs.getQuestionsCategory(cat.id)); // run all observables in parallel with forkJoin return forkJoin( observables ).pipe( // now map the array of arrays to a flattened array map(questions => this.flat(questions)) ); } // alternative to arr.flat() private flat<T>(arr: T[][]): T[] { return arr.reduce((acc, val) => acc.concat(val), []); }Debe combinar esos flujos con forkJoin o combineLatest :
getQuestions(categories: Category[]): Observable<Question[]> { return forkJoin( categories.map(category => this.cd.getQuestionsCategory(category.id)) ).pipe(tap(questions => { console.log(questions) })); // Here you can change the data structure of questions instead of just logging them }