#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/concatmap2. с 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, это правильно??