Angular8 HttpInterceptor возвращаемое значение

У меня есть базовый HttpInterceptor, в котором я использую rxjs retryWhen, чтобы повторить попытку определенное количество раз в случае сбоя службы. Если вызов службы достиг максимального количества повторных попыток, я хотел бы вернуть это методу, который первоначально инициировал вызов службы.

Мой вопрос в том, как я могу вернуть управление обратно первоначальному инициатору http-вызова? Мне нужно сделать это, чтобы централизовать контроль над обработкой повторных попыток в одном месте (перехватчик), и я хотел бы иметь возможность обратного вызова метода успеха/неудачи в вызывающей функции.

Моя проблема в том, что ошибка проглатывается глобальным обработчиком ошибок, и ничего не возвращается моему вызывающему.

Пример:

this.MyServiceCall()
        .pipe(
          map((result) => {
            console.log('this is called when the service returns success');
          }),
         )
         // If there is an error, then how can I show it?
      })
    }


export class HttpRetryInterceptorService implements HttpInterceptor {
  constructor() { }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req).pipe(
        retryWhen(errors => errors
            .pipe(
            concatMap((err:HttpErrorResponse, count) => iif(
            () => (count < 3),
            of(err).pipe(
                map(()=>{
                    console.log(count.toString())
                }),
                delay((2 + Math.random()) ** count * 200)),
                throwError(err)
            ))
        ))
    );
  }
}

person BWG    schedule 18.11.2019    source источник


Ответы (2)


Попробуйте использовать функцию catchError().

this.MyServiceCall()
    .pipe(
        map((result) => {
            console.log('this is called when the service returns success');
        }),
        catchError((error) => {
            // Do something and return either an observable or rethrow the error
            return throwError(error);
        })
    );

https://www.learnrxjs.io/operators/error_handling/catch.html

person Damian C    schedule 18.11.2019

Я думаю, вы можете использовать оператор catchError.
Вы можете по-прежнему обрабатывать ошибки в одном месте (например, в вашем перехватчике) и делегировать ошибку вызывающей стороне, выдавая ошибку в наблюдаемом объекте, на который подпишется ваша служба. к.

Примечание: если вы используете оператор throwError в перехватчике, TS должен пожаловаться на это:

intercept (req: HttpRequest<any>, next: HttpHandler) {
//~~~~~~ 
    const foo = false;

    return next.handle(req)
    .pipe(
      map(ev => foo ? ev : throwError('err!')),
    )
}

Ошибка:

Тип Observable ‹ never > не может быть назначен типу «HttpEvent».

а тип HttpEvent выглядит так:

export type HttpEvent<T> =
    HttpSentEvent | HttpHeaderResponse | HttpResponse<T>| HttpProgressEvent | HttpUserEvent<T>;

Таким образом, здесь не допускается ошибка... но вот обходной путь, который я нашел в этот ТАК пост.

intercept (req: HttpRequest<any>, next: HttpHandler) {
    const foo = false;

    return next.handle(req)
      .pipe(
        map(e => {
          if (e instanceof HttpResponse && !foo) {
            throw new HttpErrorResponse({
              error: 'err'
            });
          }

          return e;
        })
    )
  }

Теперь ошибка delegated должна быть обнаружена в обратном вызове catchError от вашей службы.

this.MyServiceCall()
    .pipe(
        map((result) => {
            console.log('this is called when the service returns success');
        }),
        catchError(err => {
            // Do something with this error...
        })
    )

РЕДАКТИРОВАТЬ

Выброс ошибки из перехватчика также может быть достигнут с помощью этого подхода:

intercept (req: HttpRequest<any>, next: HttpHandler) {
    const foo = false;

    return next.handle(req)
      .pipe(
      mergeMap(e => {
        if (!foo) {
          return throwError('err');
        }

        return of(e);
      }),
    )
  }

Я пропустил тот факт, что throwError возвращает наблюдаемое: D.

person Andrei Gătej    schedule 18.11.2019
comment
Спасибо за развернутый ответ - а как же retryWhen - в этом сложность - person BWG; 19.11.2019