#angular #typescript #rxjs #observable #rxjs6
#angular #typescript #rxjs #наблюдаемый #rxjs6
Вопрос:
У меня есть вложенная подписка, от которой я хотел бы избавиться, используя подходящий оператор RxJS. Я уже пробовал concatMap и mergeMap, с помощью которых, к сожалению, не смог решить свою проблему.
У меня есть 3 подписки, которые зависят друг от друга и запускают новую наблюдаемую в циклах forEach для каждого значения текущего цикла. Чтобы проиллюстрировать это более подробно, вот мой пример кода:
this.subscriptionOne = this.serviceOne.getStreets().subscribe((streets) => {
streets.forEach((street) => {
this.subscriptionTwo = this.serviceTwo.getMetaData(street.id).subscribe((metaDatas) => {
metaDatas.forEach((md) => {
// do some stuff and then trigger another observable..
this.subscriptionThree = this.serviceTwo.getStuff(md.id, md.type, md.name).subscribe((stuff) => {
// do some other stuff
});
});
});
});
});
Как я могу избавиться от этой вложенности с помощью RxJS?
Ответ №1:
let sub = this.serviceOne
.getStreets()
.pipe(
mergeMap(streets => {
return from(streets);
}),
mergeMap(street => {
return this.serviceTwo.getMetaData(street.id);
}),
mergeMap(metaDatas => {
return from(metaDatas);
}),
mergeMap(md => {
return this.serviceTwo.getStuff(md.id, md.type, md.name);
}),
map(stuff => {
// do your stuff
})
)
.subscribe();
metaDatas
доступно в последних двух операторах:
let sub = this.serviceOne
.getStreets()
.pipe(
mergeMap(streets => {
return from(streets);
}),
mergeMap(street => {
return this.serviceTwo.getMetaData(street.id);
}),
mergeMap(metaDatas => {
return from(metaDatas).pipe(
mergeMap(md => {
return this.serviceTwo.getStuff(md.id, md.type, md.name);
}),
map(stuff => {
// do your stuff
})
);
})
)
.subscribe();
Комментарии:
1. Значит, больше не нужно шлифовать foreach? Тогда, вероятно, это моя ошибка.. Позже я протестирую ваш подход и дам вам отзыв. Спасибо!
2. Да, вам больше не нужно
forEach
.3. Есть ли также способ объединить последние две карты слияния или я все еще могу получить доступ / выполнить итерацию по «метаданным» в функции подписки? Потому что после вызова GetStuff() в последней карте слияния мне все еще нужны некоторые свойства из «метаданных» для генерации параметров для конечного объекта.
4. Вы можете сохранить
metaDatas
в переменной, которая принадлежит методу, содержащему всю подписку, или, конечно, вы можете заключить последние два оператора в родительский оператор.5. Если вы хотите развернуть массивы, например
streets
, вы должны превратить их в наблюдаемые сfrom(streets)
помощью или вы можете просто вернуть массив иmergeMap
переиздать каждый элемент отдельноmergeMap(streets => streets)
(ну, или использоватьmergeAll
вместо этого).