如果我有combineLatest,那么使用 ngrx 和 rxjs 选择有什么不同?

Jon*_*Sud 5 rxjs ngrx angular

我有产品服务,我想从州获得最好的产品。

我可以实现此目的的一种方法是使用rxjs如下所示:

 @Injectable({ providedIn: 'root' })
 export class ProductDataService extends EntityCollectionServiceBase<Product> {
  
    bestProductsIds$ = new BehaviorSubject([]);

    bestProducts$ = combineLatest([this.entities$, this.bestProductsIds$]).pipe(
      map(([products, ids]) => products.filter((p) => ids.includes(p.id))),
      map((products) => orderBy(product, ['createdDate', ['desc']])),
      map((products) => this.toProductCard(products))
    );
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用选择器:

export const selectBestProducts = createSelector(
  ([products, ids]) => products.filter((p) => ids.includes(p.id)),
  (products) => orderBy(products, ['createdDate', ['desc']])
);


@Injectable({ providedIn: 'root' })
export class ProductDataService extends EntityCollectionServiceBase<Product> {

  bestProductsIds$ = new BehaviorSubject([]);

  bestProducts$ = combineLatest([this.entities$, this.bestProductsIds$]).pipe(select(selectBestProducts));

  ...
}
Run Code Online (Sandbox Code Playgroud)

我知道 ngrx 选择器是记忆函数,但我在这里使用combineLatest

那么在这种情况下,两种方法有什么不同呢?或者是一样的?

Хри*_*тов 0

简短的回答是没有区别,就像combineLatest您使用两个在幕后有记忆值的选择器的情况一样。

关于差异的长答案,如果我们转到文档selector内的实现,我们可以看到这些函数用于跟踪正在使用的任何更改,最终看起来像这样ngrx createSelectordefaultMemoizeisEqualCheck

export function isEqualCheck(a: any, b: any): boolean {
  return a === b;
}
Run Code Online (Sandbox Code Playgroud)

因此,每当更改中的字段state(我们依赖于选择器内部的字段)时,相关选择器将计算它的新值。您可以使用选择器做的有趣的事情是,createSeletorFactory您可以在其中提供自己的自定义比较函数,以便在需要时进行进一步优化。

关于combineLatest选择器的使用,您几乎具有相同的效果,一旦所有可观察量都发出了值,并且每次从任何这些可观察量传递新值时,新值将在流中进一步发射,将由您的逻辑处理(关于优化最受欢迎的项目的部分),在这里您可以通过distincUntilChanged您自己的自定义比较再次使用运算符来达到相同的优化效果。

总之,两种方法的行为方式相同,唯一的区别是,在第一种情况下,选择器正在执行所需的计算,而在第二种情况下,计算是在可观察到的流中处理的combineLatest