简体   繁体   English

RxJS:解开嵌套的可观察对象

[英]RxJS: untangle nested observables

I'm looking for a more readable solution than the one I have. 我正在寻找一种比我现有的解决方案更具可读性的解决方案。

I need: 1) Retrieve products from an API. 我需要:1)从API检索产品。 They are an array of objs. 它们是objs数组。 2) Filter those products based on category etc... 3) Paginate the products and return a paginated version of those products. 2)根据类别等过滤这些产品。3)对产品进行分页并返回这些产品的分页版本。

ngOnInit() {

//This gets the products from the API 
    this.drinkSubscription = this.drinkService.getAllDrinks().subscribe(drinks => {

//Save products without pagination for other purposes
      this.allDrinks = drinks;

//Get the parameter to filter products
      this.paramSubscription =  this.route.params.subscribe((params: Params) => {

//Filter the products and return a filtered array
        const filteredDrinks = this.filterService.filter(drinks, params['filter'], params['name']);

//Sort products based on the selection
        this.sorterSubscription = this.sorter.initialize(filteredDrinks).subscribe(sortedDrinks => {

//Create a pager that holds the paginated drinks in a property
          this.pagerSubscription = this.pagerService.initializePaginatedItems(sortedDrinks, 10, 5)
                                  .subscribe(pager => {
                                    this.pager = pager;
                                    this.paginatedDrinks = pager.paginatedItems;
                                  });
        });
      });
    });
  }

The sorter and the pagination are BehaviorSubjects so that I can inject next() but I'm not positive about them... You can see the level of indentation is quite high, and I was wondering if there's a way with RxJS to obtain the same results in a more readable way. 排序器和分页是BehaviorSubjects,因此我可以注入next(),但我对它们并不满意...您可以看到缩进程度很高,我想知道RxJS是否有办法获取以更易读的方式得出相同的结果。

You should be able to combine these using operators. 您应该能够使用运算符将​​它们组合在一起。 I believe the following should work. 我相信以下应该可行。

combineLatest is roughly analogous to Promise.all([p1,p2]) - only it will emit when any of the observables emits, using the previous value for the others. CombineLatest大致类似于Promise.all([p1,p2]) -仅当任何可观察对象发射时,才会使用其他对象的先前值发射。

switchMap allows you to take a value emitted from an observable, and map it to another observable. switchMap允许您获取一个可观察对象发出的值,并将其映射到另一个可观察对象。

https://www.learnrxjs.io/operators/combination/combinelatest.html https://www.learnrxjs.io/operators/transformation/switchmap.html https://www.learnrxjs.io/operators/combination/combinelatest.html https://www.learnrxjs.io/operators/transformation/switchmap.html

Eg: 例如:

let drinkObservable = this.drinkService.getAllDrinks()
let paramsObervable = this.route.params

let sub = combineLatest(drinkObservable, paramsObervable)
  .pipe(switchMap(([drinks, params]) => {
    this.allDrinks = drinks
    let filteredDrinks = this.filterService.filter(drinks, params['filter'], params['name']);
    return this.sorter.initialize(filteredDrinks)
  }))
  .pipe(switchMap(sortedDrinks => {
    return this.pagerService.initializePaginatedItems(sortedDrinks, 10, 5)
  }))
  .subscribe(pager => {
    this.pager = pager;
    this.paginatedDrinks = pager.paginatedItems;
  })

Usually subscribe within subscribe is a "code smell" which hides the need for a "flattening" strategy to be implemented with one of the flattening operators such as mergeMap (aka flatMap ), switchMap , exaustMap , concatMap (which is mergeMap with concurrency set to 1). 一般subscribesubscribe是一个“代码气味”,这隐藏了“扁平化”的策略与平坦化等运营商中的一个来实现的需要mergeMap (又名flatMap ), switchMapexaustMapconcatMap (这是mergeMap并发设置为1)。

In you specific case then, the code could become something like 那么在您的特定情况下,代码可能会变成类似

ngOnInit() {

//This gets the products from the API 
    this.drinkSubscription = this.drinkService.getAllDrinks().switchMap(drinks => {
      this.allDrinks = drinks;
      return this.route.params)
    })
    .switchMap((params: Params) => {
        const filteredDrinks = this.filterService.filter(drinks, params['filter'], params['name']);
        return this.sorter.initialize(filteredDrinks)
    })
    .switchMap(sortedDrinks => this.pagerService.initializePaginatedItems(sortedDrinks, 10, 5))
    .subscribe(pager => {
        this.pager = pager;
        this.paginatedDrinks = pager.paginatedItems;
     });
    });
  });
});

} }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM