【问题标题】:How to determine what observable been changed in Observable.merge?如何确定 Observable.merge 中哪些 observable 发生了变化?
【发布时间】:2017-08-02 08:41:36
【问题描述】:

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

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);
   });
}

此方法将返回一个可观察的客户数组。

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

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

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

然后我将所有这些合并在一起,以便我可以“组装”我必须返回的数据。如您所见,它的性能不是很好,因为它无法区分实际的 observable 发出的数据...

我如何做到这一点并确定哪个 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);
});

【问题讨论】:

    标签: javascript angular typescript rxjs reactive-programming


    【解决方案1】:

    您可以做到这一点的一种方法是让您的 Observables 发出一个具有类型的对象。例如:

    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 的链接,您可以使用它使用 click 和 interval observables。

    【讨论】:

      【解决方案2】:

      您可以使用combineLatest 代替merge。这样,您可以为每个合并的 observables 获取一个发出的值。您所要做的就是保留 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);
       });
      }
      

      【讨论】:

      • 您好纪尧姆,感谢您的回答!我试过了,但它似乎没有执行 Observable 中的代码?
      • 合并它但又一次,这是我的问题;)
      • 每个displayDataChanges 应该至少发出一个值。您可以更改页面、过滤器和排序以查看这是否有效吗?
      • combineLatest 仅在 observable 完成时发出 - merge 在任何合并的 observable 的每个 next 上发出
      • combineLatest 仅在所有组合的可观察对象都发出至少一个值时发出。结果 observable 发出一个数组,其中包含每个组合 observable 的最后发出的值。 merge 在合并的 observable 发射时发射。结果 observable 发出单个值(不是数组)。
      猜你喜欢
      • 1970-01-01
      • 2013-11-05
      • 1970-01-01
      • 2018-02-21
      • 2016-12-03
      • 1970-01-01
      • 2020-04-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多