Angular - RxJS ConcatMap - возвращает данные из обоих сервисных вызовов
Вероятно, это основной вопрос, но у меня есть приложение Angular, которое выполняет бэкэнд-вызов службы для извлечения некоторых данных, а затем использует эти данные для повторного вызова бэкэнд-службы.
Второй вызов службы зависит от первого успешного завершения, поэтому я использую функцию concatMap() из RxJS.
Тем не менее, мой код ниже возвращает только данные для второго вызова службы. Мне нужны все данные, возвращенные из обоих сервисных вызовов.
Чувствую, что я испортил вызов.pipe, но не добился большого прогресса. Заранее спасибо.
getData(id: String): Observable<any[]> {
return this.http.get<any>(`${this.baseUrl}/path/${id}`).pipe(
concatMap(
evt =>
<Observable<any[]>>(
this.http.get<any[]>(
`${this.baseUrl}/path/relatedby/${evt.child_id}`
)
)
),
retry(3),
catchError(this.handleError("getData", []))
);}
2 ответа
Функция pipe объединяет данные функции (предоставляемые в качестве аргументов) и выполняет их последовательно, и, наконец, после завершения этапов возвращает FINAL OUTPUT. Вот почему вы получаете результат только от второго вызова, потому что это была последняя функция в конвейере (последняя функция, которая возвратила значение).
например: давайте проверим это
const filterOutEvens = filter(x => x % 2)
const double = map(value => value * 2);
const sum = reduce((acc, next) => acc + next, 0);
Observable.range(0, 10).pipe(
filterOutEvens,
double,
sum)
.subscribe(console.log); // 50
здесь, из [1, 2, 3, 4, 5, 6,7, 8, 9,10], он сначала отфильтровывает четные числа, давая [1,3,5,7,9], который передается следующая функция (double), которая удваивает каждый элемент данного массива, давая [2,6,10,14,18], который передается следующей функции в pipe, которая является суммой (суммирует элементы в массиве), Функция sum является функцией LAST в конвейере и возвращает 50, что является не только возвращаемым значением sum(), но также и целого pipe().
пример кода взят из: https://blog.hackages.io/rxjs-5-5-piping-all-the-things-9d469d1b3f44
редактировать
Если вам действительно нужны данные из обоих запросов, вы можете упаковать результаты первого запроса в результат второго запроса с помощью оператора map
getData(id: String): Observable<any[]> {
return this.http.get<any>(`${this.baseUrl}/path/${id}`).pipe(
concatMap(
evt =>
<Observable<any[]>>(
this.http.get<any[]>(
`${this.baseUrl}/path/relatedby/${evt.child_id}`
).map(res =>( {"response1":evt, "response2":res}) )
)
),
retry(3),
catchError(this.handleError("getData", []))
);}
Я могу ошибаться, но двойной звук звучит излишне. Используя синтаксические скобки жирной стрелки для неявного возврата, я сделал эту работу.
this.$obs = this.route.params.pipe(
concatMap((params: Params) => {
console.log(params);
return this.useParams(params.id)
}),
share() // irrelevant
);
Дайте мне знать, если есть предостережения с этим над другими ответами.#concatMapKindaRocks
Спасибо, это сработало, а объяснение труб избавило меня от многих вопросов. Функция карты работала отлично, хотя мне просто пришлось стучать в другую трубу. Обновленный код ниже, большое спасибо еще раз за помощь, с благодарностью.
getData(id: String): Observable<any> {
return this.http.get<any>(`${this.baseUrl}/path/${id}`).pipe(
concatMap(
evt =>
<Observable<any>>(
this.http
.get<any>(`${this.baseUrl}/path/relatedby/${evt.child_id}`)
.pipe(
map(resp => ({
evtData: evt,
childData: resp
}))
)
)
),
retry(3),
catchError(this.handleError("getData", []))
);
}