Таймер останавливается при возникновении ошибки в подписке

#angular #error-handling #timer #rxjs #observable

#angular #обработка ошибок #таймер #rxjs #наблюдаемый

Вопрос:

У меня есть служба, которая запускает таймер в своем конструкторе. Таймер вызывает функцию асинхронности, которая вызывает API и должна возвращать наблюдаемое. Он работает нормально, когда все в порядке. Сейчас я пытаюсь реализовать обработку ошибок, когда API не работает. Проблема в том, что всякий раз, когда возникает ошибка, выполнение таймера останавливается.

Смотрите мой код:

 subscription : Subscription;
constructor(private httpClient : HttpClient)
{
    this.subscription = timer(0, 10000).pipe
    (
        switchMap(() => this.getData();
    }).subscribe();
}


getData(): Observable<someModel>
{
    return this.httpClient.get<someModel>(<url>)
    .pipe(
    tap(response => 
    {
        do something 
    }),
    catchError(error =>
    {
        <doSomeErrorHandling>
        return throwError(error);
    })
    );
}
 

Ответ №1:

Наблюдаемый объект закрывается при возникновении ошибки. Таким образом, вместо того, чтобы пересылать ошибку с помощью throwError функции, вы можете преобразовать ее в next уведомление с помощью of функции. Если вы беспокоитесь, что это может запутать фактический механизм обработки ответов, вы можете использовать NEVER константу RxJS, чтобы ничего не выделять из catchError блока.

Попробуйте выполнить следующее

 import { of, NEVER } from 'rxjs';
getData(): Observable<someModel>{
  return this.httpClient.get<someModel>(<url>).pipe(
    tap(response => {
      do something
    }),
    catchError(error => {
      // <doSomeErrorHandling >
      return of(error); // (or) return NEVER;
    })
  );
}
 

Также попробуйте использовать tap только для побочных эффектов. В вашем случае только с одним switchMap вы можете обрабатывать уведомления внутри подписки.

Ответ №2:

switchMap выдает ошибку, если какая-либо из его внутренних наблюдаемых [ this.getData() , в данном случае], ошибка. Вместо этого вы, вероятно, захотите перехватить ошибки на самих внутренних наблюдаемых.

Помните также, что пары RxJS испускают один error или один complete выброс. Никогда больше и никогда оба. Если ошибка достигает вашей switchMap, эта часть вашего потока выполняется навсегда. Вместо этого вы можете использовать retry для повторного создания потока с нуля.

 subscription : Subscription;
constructor(private httpClient : HttpClient){
  this.subscription = timer(0, 10000).pipe(
    switchMap(_ => this.getData().pipe(
      catchError(err => /*Do something*/)
    )
  ).subscribe();
}