多个角流一个可观察

时间:2020-07-29 16:34:16

标签: angular rxjs

我有根据特定日期从服务器中提取的数据。因此,当日期更改时,我再次从服务器查询以获取新数据。我还具有从服务器手动触发刷新的功能(用于从中提取数据的情况,因此我需要重新拉动)

private _date = new BehaviorSubject(new Date())
private _refresh = new BehaviorSubject<void>(undefined); 
readonly data$: Observable<Model[]> = combineLatest([this._date, this._refresh])
   .pipe( 
      switchMap(([date, refresh]) => this.dataService.get(date)),
      shareReplay(1) 
   )

我的视图正在使用异步管道显示data$

我需要能够操纵data$中的列表,以便跟踪列表中的已修改项。

Model {
   ...
   isModified: boolean
}

我的模型是这样的,所以如果我对元素进行更改,我希望能够将其推入数据列表(删除旧项目->替换为新的修改项目),然后发出data$更新列表。

然后,如果_date发出$data会发出该消息,并且所有修改的内容都会被清除。

我试图不直接更改列表中的项目,以便可以利用ChangeDetectionStrategy.OnPush

有没有一种方法可以组合手动更新列表和_date更新列表的过程,但是当从服务器中提取优先级时。


仅维护一个列表应该可以让我更轻松地基于数据获取汇总。随着项目的更新,我的合计值将根据修改后的列表进行更新。如果我要维护第二个已修改项列表,则如果我想要处于已修改状态的汇总值,则需要对两个列表进行比较(获取未修改的主列表中的所有项以及已修改列表中的所有项)。

批处理更新应该和

一样简单
data$.pipe(
   filter(x => x.isModified), 
   switchMap(x => dataService.update(x))
)

这是一个stackblitz,我相信它将有助于证明这一点。

在这里您可以看到我有一个组件,可用于更新从我的观察站返回的物品的名称。我希望能够修改这些项目,然后将它们存储回可观察对象中。这样,如果我想获取所有修改的项目,我可以在该可观察项上应用过滤器以获取修改的项目。同样,如果您更改了可观察到的日期将从服务器重新启动,并且已删除项目的列表也将被清除。

请参见DataService.itemNameChanged

1 个答案:

答案 0 :(得分:1)

要解决此问题,您可以使用扫描运算符在数组中保存新项目的值。

在这里创建了BehaviorSubject,以发出每个修改后的新项目的值,并使用默认数组的第一个值对其进行初始化。

  private itemModified = new BehaviorSubject<Model>(data[0]);

每次更新dateRefresh $的基本可观察值时,都应重置此值。

  readonly dateRefreshHttp$: Observable<Model[]> = combineLatest([
    this._date,
    this._refresh
  ]).pipe(
    tap(() => this.itemModified.next(data[0])),
    switchMap(([date, refresh]) =>

将扫描运算符添加到switchMap内,以便在更改累加时重新启动累加。请注意,添加的反跳运算符允许在不失去焦点的情况下多次输入字符。

   switchMap(([date, refresh]) =>
      combineLatest([from([data]), this.itemModified]).pipe(
        scan(
          (acc: any[], [data, itemModified], index: number) => {
            return acc.map(item =>
              item.id == itemModified.id ? itemModified : item
            );
          },
          [...data]
        )
      )
    ),
    debounceTime(300)
  );

最后,通过itemNameChanged函数发出一个新值。

  itemNameChanged(newName: string, item: Model) {
    const newItem: Model = {
      id: item.id,
      name: newName,
      isModified: true
    };

    this.itemModified.next(newItem);
  }

实时示例Stackblitz

相关问题