Rx JS - выполнение наблюдаемых в последовательности - PullRequest
0 голосов
/ 06 апреля 2020

Я пытаюсь запустить несколько наблюдаемых в последовательности, сохраняя их значения, но мне трудно обернуть голову вокруг правильного способа сделать это.

Абстрактная схема того, что я попытаться сделать это - создать "FruitBasket", сначала создав яблоки, а затем создавая груши, по порядку.

createApples: Observable<Apple[]> {
  // creates apples...
}

createPears: Observable<Pear[]> {
  // creates pears...
}

createFruitBasket(apples: Apple[], pears: Pear[]): Observable<FruitBasket>
{
  // create a fruit basket
}

Я бы хотел, чтобы создание яблок было завершено до попытки создания груш, и создание груш должно быть завершено до попытки создания корзины с фруктами.

Используя асинхронную / ожидающую запись, желаемый результат будет:

makeABasket() {
  let apples = await createApples();
  let pears = await createPears();
  let fruitBasket = await createFruit(apples, pears);
}

В качестве первой попытки я придумайте следующее:

makeABasket() {
  let apples: Apple[] = [];
  let pears: Pear[] = [];
  let basket: FruitBasket;

  this.createApples().subscribe((newApples) => {
    apples = apples.concat(newApples);

    this.createPears().subscribe((newPears) => {
      pears = pears.concat(newPears);

      this.createFruitBasket(apples, pears).subscribe((newBasket) => {
        basket = newBasket;
      });
    });
  });
}

Я знаю, что есть лучший способ сделать это, используя операторы Rx JS, но я не могу выбрать правильный путь. Обратите внимание, что я не хочу использовать forkJoin, поскольку хочу, чтобы функции создания выполнялись последовательно, а не параллельно.

Заранее благодарен за любые предложения.

Ответы [ 2 ]

0 голосов
/ 07 апреля 2020

Ваш код makeABasket может выглядеть примерно так

makeABasket() {
  return this.createApples().pipe(
    concatMap(apples => this.createPears().pipe(
      map(pears => {
         return {apples, pears};
      })
    ),
    concatMap(({apples, pears}) => this.createFruitBasket(apples, pears)).pipe(
      map(pears => {
         return {apples, pears, basket};
      })
    )
  )
}

При такой реализации makeABasket вернет Observable<{apples: Apple[], pears: Pear[], basket: Basket}>.

Кто бы ни нуждался в использовании яблок, груш и корзина может подписаться на эту Наблюдаемую вот так

makeABasket().subscribe(
   ({apples, pears, basket}) => {
      // do stuff with apples, pears and basket
   }
)
0 голосов
/ 06 апреля 2020

для параллельной работы вам нужна комбинационная функция concat. его сделать c: https://www.learnrxjs.io/learn-rxjs/operators/combination/concat

просто сделать

concat( // <- creates sequence.
  this.createApples(), // <- first one.
  this.createPears(), // <- once apple has been completed executes this one.
).pipe(
  scan((result, item) => [...result, item], []), // <- accumulating tuple
  skip(1), // <- apples aren't enough, skipping 1st emit.
  concatMap(([apples, pears]) => this.createFruitBasket(apples, pears)), // <- now we can set the basket.
).subscribe();
...