使用 RxJs Pipe 将 Observable 减少到不同类型

Sim*_*Ged 5 rxjs typescript angular rxjs-pipeable-operators

我有一个Observable<Recipe[]>我想减少到不同类的数组,ChartData[]以用作 highcharts 图(列和饼图)的数据源。

我正在尝试使用 RxJS 管道运算Observable<Recipe[]>符对我的数据调用 reduce 运算符,但我无法让它工作?该reduce运营商不叠代我在他们的项目Observable<Recipe[]>下面是我的尝试:

this.foodService.getAllReceipes()
  .pipe(
    reduce((array: ChartData[], value: Recipe[], i: number) => {
        const author = this.createOrFindAuthor(array, value[i]);
        author.y += 1;

        return array;
      }, new Array<ChartData>())
  )
  .subscribe(data => this.chartData$ = of(data.sort((a, b) => b.y - a.y)));
}
Run Code Online (Sandbox Code Playgroud)

getAllRecipes() 返回 Observable<Recipe[]>

this.chartData$Observable<ChartData[]>

我试图将其减少到ChartData[]. 我已经能够在subscribe操作员中做到这一点,并且图表显示了预期的数据,但我认为我应该能够作为可管道操作员来做到这一点?这是作为订阅的一部分完成的减少:

this.foodService.getAllReceipes()
  .subscribe((data) => {
    const list = data.reduce((arr: ChartData[], v: Recipe) => {
      const author = this.createOrFindAuthor(arr, v);
      author.y += 1;

      return arr;
    }, new Array<ChartData>());

    this.chartData$ = of(list.sort((a, b) => b.y - a.y));
  });
Run Code Online (Sandbox Code Playgroud)

我曾尝试subscribe在 pipeable 中使用代码,reduce但我收到编译错误,说该方法需要Recipe[]该值。但是如果我使用数组,那么我只能从 Observable 中获取第一个元素(或者我只是获取 Observable 并且需要对此做些什么?)

这是可能的,还是我关于可管道操作符应该如何在 Observable 上工作的思考过程是错误的?

参考这里是模型和 createOrFindAuthor 函数:

export class Recipe {

    public Title: string;
    public Author: string;
    public Source: string;
    public Page: number;
    public Link?: string;
}

export class ChartData {
    name: string;
    y: number;
}

private createOrFindAuthor(array: ChartData[], recipe: Recipe): ChartData {
  const name = (recipe.Author.length > 0 ? recipe.Author : 'UNKNOWN');

  let found = array.find(i => i.name === name);

  if (!found) {
    const newData = new ChartData();
    newData.name = name;
    newData.y = 0;
    array.push(newData);

    found = newData;
  }

  return found;
}
Run Code Online (Sandbox Code Playgroud)

Sim*_*Ged 5

所以Chau Tran 让我走上了正确的道路。显然我需要将switchMapObservable 转换为 a Recipe[],然后reduce操作员很乐意接受 aRecipe作为值。解决方法如下:

this.foodService.getAllReceipes()
  .pipe(
    switchMap(data => data as Recipe[]),            <<== ADDED THIS

    reduce((array: ChartData[], value: Recipe) => {
        const author = this.createOrFindAuthor(array, value);
        author.y += 1;

        return array;
      }, new Array<ChartData>()),

      switchMap(data => this.chartData$ = of(data.sort((a, b) => b.y - a.y)))
  )
  .subscribe();
Run Code Online (Sandbox Code Playgroud)