Обработка двух HTTP-запросов (Angular + RxJS)

Это мой первый угловой проект, и я до сих пор плохо знаком с Observables и RxJS. В моем проекте сначала я хочу получить все уведомления с помощью запроса на получение. После этого я хочу получить идентификатор последнего уведомления, чтобы я мог отправить почтовый запрос на сервер, чтобы пометить их все как прочитанные. Итак, код в сервисе выглядит так:

 getNotifications(limit: number, page: number): any {
    return this.http
      .get<INotifications>(
        `${API_URL}/notifications?direction=desc&limit=${limit}&order_by=created_at&page=${page}`
      )
      .pipe(
        switchMap((response) => {
          const id = response.data[0].id;
          return this.markNotificationsAsRead(id);
        })
      );
  }

markNotificationsAsRead(id: number) {
    return this.http.post(`${API_URL}/notifications/${id}/mark_all_as_read`, {
      id,
    });
  }

Я пытался использовать switchMap и mergeMap.

операторы, но я получаю

RangeError: недопустимая длина массива

Код в компоненте:

 fetchData() {
    this.notificationsService.getNotifications(this.limit, this.meta?.next_page || 1).subscribe(
      (response) => {
        this.notifications = [...this.notifications, ...response.data];
        this.meta = response.meta;
        this.isLoading = false;
        // const mostRecentNotification = response.data[0].id;
        // this.markNotificationsAsRead(mostRecentNotification);
      },
      (error) => {
        this.handleErrors(error);
      }
    );
  }

Кстати: я могу заставить его работать, удалив этот закомментированный раздел в функции fetchData и просто вернув запрос на получение без передачи другому оператору, но я хотел попробовать и сделать это в сервисе. Любые идеи, почему это не сработает?


person user13067004    schedule 09.02.2021    source источник
comment
Если вы отлаживаете это, каково значение response?   -  person RJM    schedule 09.02.2021
comment
Вы собираетесь сделать return this.markNotificationsAsRead(id)? Это вернет значение вашего почтового запроса методу fetchData(), а не значение вашего запроса на получение.   -  person RJM    schedule 09.02.2021
comment
Я получаю объект со всеми предоставленными данными: Данные объекта: (5) [{…}, {…}, {…}, {…}, {…}] meta: {prev_page: null, current_page: 1, next_page: 2 } прото: Объект   -  person user13067004    schedule 09.02.2021
comment
Является ли это значение response одинаковым в подписке switchMap() И fetchData()?   -  person RJM    schedule 09.02.2021
comment
Вы собираетесь вернуть this.markNotificationsAsRead(id)? Это вернет значение вашего почтового запроса в метод fetchData(), а не значение вашего запроса на получение. – RJM 1 мин назад Я хочу вернуть данные из запроса GET.   -  person user13067004    schedule 09.02.2021
comment
Является ли это значение ответа одинаковым в подписке switchMap() И fetchData()? – РДМ Да.   -  person user13067004    schedule 09.02.2021
comment
Что произойдет, если вы замените switchMap() на tap()?   -  person RJM    schedule 09.02.2021
comment
Он не выполняет post req.   -  person user13067004    schedule 09.02.2021
comment
Верно, я этого и ожидал, но все ли в fetchData() работает? Вы все еще получаете RangeError? Получаете ли вы данные уведомлений и можете ли их отображать и т. д.?   -  person RJM    schedule 09.02.2021
comment
Да, сейчас отображаются.   -  person user13067004    schedule 09.02.2021
comment
Я напишу ответ, который, надеюсь, решит это для вас сейчас.   -  person RJM    schedule 09.02.2021
comment
Спасибо :)   -  person user13067004    schedule 09.02.2021


Ответы (1)


Итак, если я правильно понимаю, вы пытаетесь получить некоторые данные (уведомления), сделать почтовый запрос, когда данные вернутся, а затем отобразить данные в своем компоненте.

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

Проблема

Проблема, как я вижу, здесь:

 switchMap((response) => {
            const id = response.data[0].id;
            return this.markNotificationsAsRead(id);
          })

Что это делает, так это возвращает значение markNotificationsAsRead() вашему subscribe, а не данные уведомлений, которые вы ожидаете.

Решение

Вы правильно используете switchMap(), чтобы сделать два запроса в одном. Я считаю, что все, что вам нужно, это одна небольшая модификация:

switchMap((response) => {
            const id = response.data[0].id;
            return this.markNotificationsAsRead(id).pipe(map(() => response));
          })

Добавляя pipe(map(() => response)), вы возвращаете значение первого наблюдаемого, но при этом подписываетесь на второй (и, таким образом, делаете запрос на публикацию).

person RJM    schedule 09.02.2021
comment
Конечно, как я могу отметить это, хотя? У меня недостаточно репутации, чтобы увидеть мой голос :( - person user13067004; 09.02.2021
comment
Не беспокойтесь, эта ссылка должна объяснять: meta.stackexchange.com/questions/5234/ - person RJM; 09.02.2021