RXJS:将来自foreach的多个调用合并为一个可观察的对象 [英] RXJS: Combining multiple calls from foreach into a single observable

查看:76
本文介绍了RXJS:将来自foreach的多个调用合并为一个可观察的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一段时间以来,我一直在尝试组合多个异步调用,每当我接近时,我都会陷入尝试解决的foreach循环中.

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

推荐答案

首先,我喜欢将其放入专用函数中的想法,以便可以将接口与实现分开.

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.

  • 您首先需要一个 Category 类别.
  • 对于每个类别,您都想调用一个服务函数,该函数返回一个可观察到的 Question 数组.
  • 您要异步从函数中返回扁平化的问题数组

我可以通过以下方式解决此问题:

I would approach this by:

  • 创建可观察数组.这可以帮助您了解您的入门知识
  • forkJoin 可观察的数组.本身将返回一个二维数组
  • 二维数组映射到平面数组
  • 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), []);
}

这篇关于RXJS:将来自foreach的多个调用合并为一个可观察的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆