如何确定Observable.merge中哪些observable已被更改?

时间:2017-08-02 08:41:37

标签: javascript angular typescript rxjs reactive-programming

下面你可以看到我为了可读性和清晰度而简化的代码:

connect(): Observable<Customer[]> {
   const displayDataChanges = [
     this._customerDatabase.dataChange,
     this._filterChange,
     this._sort.mdSortChange,
     this._paginator.page
   ];
   return Observable.merge(...displayDataChanges).map(() => {
     let data = this._customerDatabase.data.slice();
     data = this.getFilteredData(data);
     data = this.getSortedData(data);
     const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
     return data.splice(startIndex, this._paginator.pageSize);
   });
}

此方法将返回一个Observable Customers数组。

下面的部分定义了一个Observables数组:

const displayDataChanges = [
      this._customerDatabase.dataChange,
      this._filterChange,
      this._sort.mdSortChange,
      this._paginator.page
];

每当其中一个发出数据时,我都希望我的客户数组能够改变。 (当我加载数据时,当我的过滤器发生变化时,当我选择其他排序机制时以及当我更改页面时)

然后我将所有这些合并在一起,这样我就可以组装&#39;我的数据必须返回。正如您所看到的,它不是非常高效,因为它没有区分实际可观察​​数据发出的数据......

如何完成此操作并确定哪个observable已更改? (下面的伪代码)

return Observable.merge(...displayDataChanges).map(() => {

 **[ALWAYS]**
 let data = this._customerDatabase.data.slice();

 **[IF MY SORTING HAS CHANGED]**
 data = this.getSortedData(data); /* After which i will change the dataSet */
 **[IF MY FILTER HAS CHANGED]**
 data = this.getFilteredData(data);

 **[ALWAYS]**
 const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
 return data.splice(startIndex, this._paginator.pageSize);
});

2 个答案:

答案 0 :(得分:1)

执行此操作的一种方法是使Observable发出具有类型的对象。例如:

connect(): Observable<Customer[]> {

   const typifier = (type) => {
       return (val) => {
           return { type: type, value: val };
       }
   };

   const displayDataChanges = [
       this._customerDatabase.dataChange,
       this._filterChange.pipe(map(typifier('filterChange'))),
       this._sort.mdSortChange.pipe(map(typifier('sortChange'))),
       this._paginator.page
   ];

   return merge(...displayDataChanges).pipe(map(obj => {

       let data = this._customerDatabase.data.slice();

       if (obj.type === 'filterChange')
       {
           data = this.getFilteredData(data);
       }

       if (obj.type === 'sortChange')
       {
           data = this.getSortedData(data);
       }

       const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
       return data.splice(startIndex, this._paginator.pageSize);
   }));
}

这里是指向code snippet的链接,您可以使用该链接使用单击和间隔可观察值。

答案 1 :(得分:0)

您可以使用combineLatest代替merge。这样,您可以为每个合并的observable获取一个值。您所要做的就是保留对mdSortChange_filterChange的最后一个值的引用,以检查它们是否已更改。

CombineLatest documentation

connect(): Observable<Customer[]> {
  const displayDataChanges = [
    this._customerDatabase.dataChange,
    this._filterChange,
    this._sort.mdSortChange,
    this._paginator.page
  ];

  let lastFilter = null;
  let lastSort= null;

  return Observable
    .combineLatest(...displayDataChanges)
    .map(([newData, newFilter, newSort, newPage]) => {
      let data = this._customerDatabase.data.slice();

      if (newFilter !== lastFilter) {
        data = this.getFilteredData(data);
        lastFilter = newFilter ;
      }

      if (newSort !== lastSort) {
        data = this.getSortedData(data);
        lastSort = newSort;
      }

      const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
      return data.splice(startIndex, this._paginator.pageSize);
 });
}