Angular2, RxJS Тема HTTP-запроса - при запросе ошибки не срабатывает снова

У меня проблема при получении ответа об ошибке http (ошибка проверки 422 из серверной части).

После получения ответа об ошибке http я не могу повторно запустить запрос (при нажатии кнопки).

1) У меня есть свойство объекта, и я вызываю .next (whatEverDataForTheRequest), чтобы отправить запрос к API.

2) В конструкторе я подписываюсь на тему (.asObservable), и здесь все идет нормально, когда ответ успешен, но не когда возникает ошибка.

Код в настоящее время такой:

// Properties -> Subject + Observable, used when button is clicked
private saveBookingSubject: Subject<BookingUpdateInterface> = new Subject<BookingUpdateInterface>();
private saveBookingObservable = this.saveBookingSubject.asObservable();

Когда нажимается кнопка, я создаю полезную нагрузку / объект и передаю его следующим образом:

this.saveBookingSubject.next(payload)

Затем в конструкторе у меня есть следующий код, который запускается при вызове .next.

const sub = this.saveBookingObservable.pipe(
  tap(data => {
    this.bookingError = null;
    this.dialogCanClose = false;
  }),
  debounceTime(500),
  switchMap(booking => {
    return this.bookingService.update(booking).pipe(catchError(error => throwError(error)));
  })
).subscribe((response: any) => {
  // This works - Called on success
  console.log('ok', response);
}, (http: HttpErrorResponse) => {
  // This works - Gets called on error
  console.log(http);
});

Успешный запрос работает так, как задумано - но когда от бэкэнда поступает ошибка, то вызывается:

this.saveBookingSubject.next(payload)

... полностью игнорируется при каждом нажатии кнопки -> И логика подписки никогда не срабатывает.

Что мне здесь не хватает? (Отписываюсь в ngOnDestroy)

Спасибо!


РЕДАКТИРОВАТЬ РЕДАКТИРОВАТЬ - РАБОЧИЙ ПРИМЕР (как опубликовано Мартином)

const sub = this.saveBookingObservable.pipe(
  debounceTime(500),
  switchMap(booking => {
    return this.bookingService.update(booking).pipe(
      catchError(httpError => {
        this.bookingError = httpError.error.data;
        return of(null);
      })
    );
  }),
  retry(1)
).subscribe((response: any) => {
    // Handle success
  }
});

person Klemme    schedule 26.01.2020    source источник
comment
Похоже, это неполные коды, я не могу воспроизвести проблему, поэтому, думаю, вам может понадобиться оператор retry   -  person Chunbin Li    schedule 26.01.2020


Ответы (1)


Проблема, с которой вы столкнулись, сводится к "наблюдаемому контракту". Одна цепочка может генерировать только одно уведомление об ошибке, поэтому, когда ваш this.bookingService.update выдает ошибку, цепочка удаляется (отписывается). Поэтому отправка дополнительных next уведомлений от saveBookingObservable не имеет никакого эффекта.

В зависимости от того, что именно вы хотите сделать, кажется, что вы можете просто добавить retry() после switchMap(), что автоматически приведет к повторной подписке.

person martin    schedule 26.01.2020
comment
Привет, Мартин - Вы абсолютно правы, добавив retry (1), все работает так, как ожидалось. Я догадывался, что контракт не разорван, но явно ошибался - спасибо! - person Klemme; 27.01.2020