【问题标题】:rxjs groupBy and compare each emitted object with latest of other groupsrxjs groupBy 并将每个发出的对象与最新的其他组进行比较
【发布时间】:2021-01-13 20:10:38
【问题描述】:

是否可以使用 rxjs 对对象属性进行分组,并将一组的新发出事件与其他组的最新值进行比较?在此之后将所有流合并为一个。

例如,我有 5 个房间,每个房间都有一盏灯。发射器随机打开或关闭其中一个房间的灯。我想知道管道中所有房间的灯何时关闭或打开,以及何时将属性 allLightsOff 添加到发射的对象。

const source = interval(1000).pipe(
  map((e) => {
    return {
      iteration: e,
      room: Math.floor(Math.random()*5),
      lightOn: Math.round(Math.random()),
      allLightsOff: null
    };
  }),
  groupBy((o) => o.room)
  // how to compare one room with all others?
  // how to merge alls groups to a single stream together again?
);
const subscribe = source.subscribe((o) => console.log(o));

【问题讨论】:

  • 您是否有这些房间的任何状态上下文以及每个房间的当前状态数据以便随时访问它?
  • @Zac,你说的状态上下文是什么意思?我有一个类似上面模拟的流。
  • 我的意思是,你在哪里存储或保存这些发出的数据?
  • @Zac,视情况而定,有时它以流的形式进入,有时作为时间序列数据库中的数组。

标签: javascript rxjs reactive-programming


【解决方案1】:

我认为您可以使用ReplaySubject(1)switchMap + combileLatest 来执行以下操作:

const source = interval(1000).pipe(
  map((e) => {
    return {
      iteration: e,
      room: Math.floor(Math.random()*5),
      lightOn: Math.round(Math.random()),
      allLightsOff: null
    };
  }),
  groupBy((o) => o.room, undefined, undefined, () => new ReplaySubject(1)),
  scan((allGroups, group) => [...allGroups, group], []),
  switchMap(groups => combineLatest(groups)),
  map((rooms: any[]) => {
    if (rooms.every(room => room.lightOn)) {
      console.log(rooms);
      return 'all on';
    } else if (rooms.every(room => !room.lightOn)) {
      console.log(rooms);
      return 'all off';
    }
    return 'some on, some off';
  }),
);

const subscribe = source.subscribe((o) => console.log(o));

每个新组是ReplaySubject(1),它会重放其最后一个值,因此当添加一个新组时,它将由scan 累加,然后combileLatest 将订阅新列表。

现场演示:https://stackblitz.com/edit/rxjs-u9w73k?devtoolsheight=60

【讨论】:

  • 谢谢马丁,好主意。给我留下一个问题,我怎么知道哪个房间是最新的,所以我可以用更新的属性 allLightsOff:1 发出这个?
  • 我认为每个房间都有iteration属性,索引由interval生成,所以iteration最高的房间是最后一个发生变化的房间。
  • 迭代只是在我的示例中越来越多。实际上我没有它,因为它是一个随机的 uuid。
  • @Manuel 可以使用map((room, index) => ({ ...room, index })),并添加map()自动生成的索引。
猜你喜欢
  • 1970-01-01
  • 2019-02-26
  • 2020-08-13
  • 1970-01-01
  • 2011-06-27
  • 1970-01-01
  • 1970-01-01
  • 2017-09-21
  • 1970-01-01
相关资源
最近更新 更多