Rx

时间:2018-12-07 19:40:41

标签: rxjs reactive

我有一个Observable<EntityId[]>,可以为每个EntityId获取一个Observable<Entity>。我想将其转换为Observable<Entity[]>。以下内容以简单的方式解决了该问题:

idsStream
    .Select(ids => ids
        .Select(id => StreamEntity(id))
        .CombineLatest())
    .Switch()

问题在于,每次idsStream发出一些新的ID时,每个实体订阅都将关闭,而新的实体订阅将被打开。我只想关闭EntityId[]中不再包含的Observable,并为添加的ID打开新的流。

在我看来,应该为此有一个运算符,但我什么也找不到。有谁知道这样的运算符,还是我应该自己编写/实现。如果是这样,以下内容似乎是一个主意

// Only select for new elements and reuses former values
SelectAndKeep: Observable<TIn[]> -> (TIn -> TOut) -> Observable<TOut[]>

// Only subscribes/unsubscribe to new/removed observables
SwitchKeepAndCombineLatest: Observable<Observable<T>[]> -> Observable<T[]>

Observable<EntityId[]> idsStream

Observable<Observable<Entity>[]> entitiesStreamStream = 
    idsStream.SelectAndKeep(id => StreamEntity(id))

Observable<Entity[]> entitiesStream = entitiesStreamStream
    .SwitchKeepAndCombineLatest()

对这种情况有任何想法或经验吗?似乎很通用,因此应该存在一个好的解决方案...

1 个答案:

答案 0 :(得分:0)

根据我对您问题的理解,我为您提供此实现:

interface Entity {
  id: number;
  title: string;
}
const entities: Entity[] = [{id: 1, title: 'foo1'}, {id: 2, title: 'foo2'}, {id: 3, title: 'foo3'}];

const entities$ = of(entities); // Observable of Entity[]

const ids$ = of([1,2], [1,3]); // Observable of ids.

ids$.pipe(mergeMap(ids => { 
  // Transform collection of id to collection of entity
  return entities$.pipe(map((entities) => {
      // from whole collection of entity, let keep what is present on ids.
      return entities.filter(entity => ids.findIndex(id => entity.id === id) !== -1);
  }));
})).subscribe(console.log);

entities$“可观察”应该是“可热观察”(例如BehaviorSubject),以便始终接收商店中可用的最后一个实体。 mergeMap并行合并并将ids$流中的每个新数据映射到按原始id集合过滤的实体集合。

live example