Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

1.6K
Views
RXJS: Combining multiple calls from foreach into a single observable

I've been trying to combine multiple async calls for a while now, and everytime I get close, I get stuck at a foreach loop I'm trying to solve.

At the moment I pass an array of categories to a function, which will return an observable containing an array of all the questions (of all the categories combined).
I was thinking of

  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?
    });
  }

I would then be able to use it like this:

   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);
      })
    );

This is as close as I could get to someone's recommendation on my previous question. I wanted to add this to my original question, but I feel this wouldn't be the right thing to do since I'm no longer struggling with nested observables, but rather with looping over them.

EDIT
Tried something else, but I doubt this is the right way to do it

  getQuestions(categories: Category[]): Observable<Question[]> {
    let ques = categories.map(c =>
      this.cs.getQuestionsCategory(this.auth.token, c.id)
    );

    return merge(...ques);
  }
over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Firstly, I like the idea of putting this into a dedicated function, so that you can separate the interface from the implementation.

The problem you want to solve should be doable in the pipe, it's just a case of working out what's going on.

  • You start off with an array of Category.
  • For each catgory, you want to call a service function, which returns an observable array of Question.
  • You want to return that flattened array of questions from the function asynchronously

I would approach this by:

  • Creating the observable array. This helps you understand what you're starting with
  • forkJoin the observable array. By itself this will return a 2-dimensional array
  • map the 2-dimensional array to a flat array
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), []);
}
over 4 years ago · Santiago Trujillo Report

0

You should combine those streams with forkJoin or 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
}
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!