【问题标题】:RxJS: untangle nested observablesRxJS:解开嵌套的可观察对象
【发布时间】:2018-09-19 14:37:28
【问题描述】:

我正在寻找一种比现有解决方案更具可读性的解决方案。

我需要: 1) 从 API 中检索产品。它们是一组对象。 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;
                                  });
        });
      });
    });
  }

排序器和分页是 BehaviorSubjects 以便我可以注入 next() 但我对它们并不积极... 您可以看到缩进级别相当高,我想知道 RxJS 是否有办法以更易读的方式获得相同的结果。

【问题讨论】:

    标签: javascript stream rxjs rxjs6


    【解决方案1】:

    您应该能够使用运算符将​​这些组合起来。我相信以下应该有效。

    combineLatest 大致类似于Promise.all([p1,p2]) - 只有当任何可观察对象发出时它才会发出,其他的使用以前的值。

    switchMap 允许您获取从可观察对象发出的值,并将其映射到另一个可观察对象。

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

    例如:

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

    【讨论】:

      【解决方案2】:

      通常,subscribe 中的 subscribe 是一种“代码气味”,它隐藏了使用诸如mergeMap(又名flatMap)、@987654325 等扁平化运算符之一实施“扁平化”策略的需要@、exaustMapconcatMap(即mergeMap,并发设置为1)。

      那么在你的具体情况下,代码可能会变成这样

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

      }

      【讨论】:

        猜你喜欢
        • 2022-11-25
        • 2020-08-28
        • 2019-02-19
        • 2023-01-25
        • 1970-01-01
        • 1970-01-01
        • 2016-06-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多