вложенные наблюдаемые, выполняемые один за другим после завершения

#angular #rxjs

Вопрос:

я реализую угловое решение, чтобы сначала получить все элементы в базе данных, после завершения я затем получаю текущее выбранное поле из базы данных, а затем сопоставляю элементы с полем. мне нужно, чтобы все товары были оплачены, затем, получив поле в конце, выполните сопоставление, у меня есть следующий код, который работает, но он немного грязный, выполняя вложенные наблюдаемые, у кого-нибудь из вас есть более чистое решение?? я нашел в документации решение os swithMap, но я думаю, что оно не подходит для моего случая, потому что карта переключения не работает с верхней наблюдаемой для завершения выполнения внутренней

 this.getItems().subscribe(items => {
        this.itemsInDataBase = items;
    this.loadActiveBox().subscribe(box => {
        this.selectedBox= box;

        this.selectedBox?.versions.forEach((version, index) => {
            this.itemsInDataBase.forEach((itemInDatabase, index) => {
                version.items.forEach((item, index) => {
                        this.insertItemInbox(item, itemInDatabase, version);
                    }
                );
            });
        });
 

grazie mille

Комментарии:

1. Если вы хотите добавить порядок к своим вызовам, concatMap это было бы приемлемым вариантом, см. learnrxjs.io/learn-rxjs/operators/transformation/concatmap

2. с concat map я должен добавить задержки, я думаю, что это не так чисто.

3. Единственная задержка, которую я мог видеть здесь, — это concatMap, ожидающий завершения ваших внешних наблюдаемых объектов. Что вы и делаете прямо сейчас, так что я бы не увидел в этом проблемы. Во всяком случае, тем временем Майкл предложил хорошую альтернативу.

Ответ №1:

switchMap Оператор RxJS может использоваться там, где внутренняя наблюдаемая зависит от внешней наблюдаемой. В вашем случае, поскольку обе наблюдаемые кажутся независимыми, вы могли бы использовать forkJoin функцию.

 forkJoin({
  items: this.getItems(),
  box: this.loadActiveBox()
}).pipe(
  tap({
    next: ({items, box}) => {
      this.itemsInDataBase = items;     // <-- are these needed?
      this.selectedBox = box;
    }
  })
).subscribe({
  next: ({items, box}) => {
    box?.versions.forEach(version =>
      items.forEach(itemInDatabase =>
        version.items.forEach(item =>
          this.insertItemInbox(item, itemInDatabase, version)
        )
      )
    )
  },
  error: (error: any) => {
    // handle errors
  }
});
 

Комментарии:

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

2. @Ares: Зависит ли HTTP-запрос this.loadActiveBox() от ответа на this.getItems() запрос? Обратите внимание, что я спрашиваю о запросе. Не то, что делается с их ответами.

3. запросы независимы, но ответы да, я понимаю, что вы имеете в виду.

4. Если запросы независимы, вы можете использовать forkJoin функцию. Кроме этого, я не совсем ясно понимаю вопрос.

5. у меня есть дополнительный вопрос, я хочу выполнить первое наблюдаемое только один раз, а затем использовать его каждый раз. затем я выполняю его в конструкторе и передаю ссылку на fork join, это правильно??