RxJS: распутать вложенные наблюдаемые - PullRequest
0 голосов
/ 19 сентября 2018

Я ищу более удобочитаемое решение, чем у меня.

Мне нужно: 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, чтобы я мог добавить их далее ()но я не уверен в них ... Вы можете видеть, что уровень отступа довольно высок, и мне было интересно, есть ли способ с RxJS получить те же результаты в более читабельном виде.

Ответы [ 2 ]

0 голосов
/ 20 сентября 2018

Обычно subscribe в subscribe - это «запах кода», который скрывает необходимость реализации стратегии «сглаживания» с помощью одного из операторов сглаживания, таких как mergeMap (он же flatMap), switchMap, exaustMap, concatMap (что составляет 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;
     });
    });
  });
});

}

0 голосов
/ 19 сентября 2018

Вы должны быть в состоянии объединить их, используя операторы.Я считаю, что следующее должно работать.

combLatest примерно аналогичен 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;
  })
...