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", []))
);

}

Другие вопросы по тегам