缓冲分组可观察量

时间:2016-09-30 15:26:04

标签: reactive-programming rxjs

我有以下类和数组

class Hero {
    id: number;
    name: string;
}

const HEROES: Hero[] = [
    { id: 11, name: 'Narco' },
    { id: 12, name: 'Narco' },
    { id: 13, name: 'Bombasto' },
    { id: 14, name: 'Bombasto' },
    { id: 15, name: 'Bombasto' },
    { id: 16, name: 'Dynama' },
    { id: 17, name: 'Dynama' },
    { id: 18, name: 'Dynama' },
    { id: 19, name: 'Dynama' },
    { id: 20, name: 'Dynama' }
];

我想创建一个将HEROES数组视为源的observable,将数组按name分组并将结果作为单个数组发出,即我应该最终得到三个数组,一个用于Narco,一个用于Bombasto,一个用于Dynama

我可以按如下方式创建我的源可观察

var heroSource = Observable.create((observer:any) => {
            HEROES.forEach((hero: Hero) => {
                observer.next(hero);
            })
        });

然后我可以使用groupBy分组英雄,即

var groupHeroSource = heroSource
            .groupBy((hero: Hero) => {return hero.name});

这有效地为我提供了尽可能多的可观察量,因为我的HEROES数组中有不同的名称(本例中为3个)。但是,这些将作为一个序列发出,理想情况下我希望buffer直到heroSource完成。如何在我的分组可观察对象的rxjs中使用buffer运算符,以便发出单个集合?

1 个答案:

答案 0 :(得分:3)

首先,您可以更简单地创建初始可观察量:

var heroSource = Observable.from(HEROES);

接下来,您的groupBy映射器/选择器可以缩写为:

var groupHeroSource = heroSource.groupBy((hero: Hero): string => hero.name);

为了解决原始问题,我需要缓冲流,因为它们准备好了一个时间为0的缓冲区就能完成工作(我想应该有一个更优雅的解决方案),使用take(1)来只有第一个结果(并避免重复缓冲)然后合并所有:

var finalGroup = groupHeroSource.map((ob) => ob.bufferWithTime(0).take(1)).mergeAll();

请注意,由于您的数组实际上是静态的,将它放在流中然后映射它可能不是最简单的解决方案,您可以简单地减少它:

var grouped = HEROES.reduce((acc: any, hero: Hero) => {
  acc[hero.name] = acc[hero.name] || [];
  acc[hero.name].push(hero);
  return acc;
}, {});

由于Object.values不是标准的,你必须迭代键才能得到一个数组,但它可能更适合你的需要