Как предотвратить распространение наблюдаемой ошибки? - PullRequest
0 голосов
/ 11 июля 2019

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

export class ApiService {
    interval$: BehaviorSubject<number> = new BehaviorSubject<number>(0); // Feed a 0 initially so it makes HTTP call even if auto-refresh is 0
                                                                         // variable ending in $ is common convention to mean it is an Observable
    constructor(private http: HttpClient) { }

    getApi(url: string, auto_refresh=false) {
        if (!auto_refresh)
            return this.http.get(url);

        return this.interval$.pipe(
            switchMap(duration => {
                if (duration == 0)
                    return this.http.get(url);

                return interval(duration * 1000).pipe(
                    startWith(0),
                    switchMap(() => this.http.get(url))
                )
            })
        );
    }

    updateInterval(i: number) {
        this.interval$.next(i);
    }
}

Это прекрасно работает, если я что-то делаю в компоненте, например:

this.subscription = this.apiService.getApi('/api/foo/bar', true).subscribe(tempjson => {
    this.foo = tempjson;
});

ЕслиУ меня установлен интервал автоматического обновления 1, он будет /api/foo/bar каждую секунду.

Проблема в том, что API возвращает код возврата, отличный от 200.В этом случае, кажется, что он нарушает Observable и никогда не пытается выполнить GET.

Я не могу понять причину этого.Я предполагаю, что какое-то исключение распространяется из наблюдаемого и уничтожает наблюдаемое.Но я не могу понять, как это предотвратить.Я попытался добавить обработчик ошибок в подписку, но это не имеет никакого значения:

this.subscriptions.push(this.apiService.getApi('/api/modem/lte_signal_info', true).subscribe(tempjson => {
  this.lte_signal_info = tempjson;
},
error => {
  console.log(error)
}));

Я также попытался отловить ошибку в самой службе, но кажется, что вы не можете просто проглотитьисключение, вы должны сбросить его, когда вы закончите согласно: https://angular.io/guide/http#getting-error-details

1 Ответ

1 голос
/ 11 июля 2019

Согласно схеме наблюдаемых, если ошибка (исключение) возникает в наблюдаемом конвейере, тогда наблюдаемая находится в состоянии ошибки и не может выдавать новые значения (https://blog.angular -university.io / rxjs-error-processing / / ) и его можно считать завершенным [то есть он не может выдавать новые значения]. По этой причине, если API возвращает код, отличный от 200, ваша наблюдаемая находится в состоянии ошибки и не будет выдавать новые значения.

Теперь, чтобы сохранить наблюдаемую исходную информацию в реальном времени в случае ошибки (в вашем случае interval наблюдаемая продолжит работу в случае ошибки), обработайте ошибку в наблюдаемой, которая выдает ошибку, используя оператор catchError. Измените свой код следующим образом:

getApi(url: string, auto_refresh=false) {
      if (!auto_refresh)
          return this.http.get(url);

      return this.interval$.pipe(
          switchMap(duration => {
              if (duration == 0)
                  return this.http.get(url)
                             .pipe(
                               catchError(err => {

                                 //return an observable as per your logic
                                 //for now I am returning error wrapped in an observable
                                 //as per your logic you may process the error
                                 return of(err);
                               })
                             );

              return interval(duration * 1000).pipe(
                  startWith(0),
                  switchMap(() => {
                    return this.http.get(url)
                             .pipe(
                               catchError(err => {
                                 //return an observable as per your logic
                                 //for now I am returning error wrapped in an observable
                                 //as per your logic you may process the error
                                 return of(err);
                               })
                             );
                  })
              )
          })
      );

Конечно, вы можете написать функцию для помещения дубликата кода [как вы можете видеть в приведенном выше коде] и использовать этот метод.

Надеюсь, что это даст вам идею и решит вашу проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...