Как отправить данные об ошибке на сервер в Angular 4+ HttpInterceptor

Я реализовал HttpInterceptor для перехвата ошибок запросов в своем приложении Angular 5. Моя цель - отправить на сервер еще один запрос REST POST, который сохраняет журнал ошибок. Это выглядит так:

@Injectable()
export class RestErrorHandler implements HttpInterceptor {

private readonly ERROR_LOGGER_PATH: string = '/logger/errorEntry';

constructor(private http: HttpClient, private restUtils: RestApiUtilsService) {}

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req).catch((errorReponse: HttpErrorResponse) => {
        return this.handleRestError(errorReponse, req, next);
    });
}

public handleRestError(error: HttpErrorResponse, req: HttpRequest<any>, next: HttpHandler): ErrorObservable {
    let errorMessage = this.prepareErrorMessage(error);
    let entry = this.prepareEntry(errorMessage);
    this.http.post(this.restUtils.getUrl(this.ERROR_LOGGER_PATH), JSON.stringify(entry), this.restUtils.jsonResponseRequestOptions()).subscribe();
    return Observable.throw(error);
}
}

export const ErrorInterceptorProvider = {
provide: HTTP_INTERCEPTORS,
useClass: RestErrorHandler,
multi: true,
};

Позже я регистрирую ErrorInterceptorProvider в качестве провайдера в модуле.

При запуске приложения возникает ошибка:

Cannot instantiate cyclic dependency! HttpClient ("[ERROR ->]"): in NgModule AppModule in ./AppModule@-1:-1
Cannot instantiate cyclic dependency! HttpClient ("[ERROR ->]"): in NgModule AppModule in ./AppModule@-1:-1
at NgModuleProviderAnalyzer.parse (compiler.js:19542)
at NgModuleCompiler.compile (compiler.js:20131)
at JitCompiler._compileModule (compiler.js:34430)
at eval (compiler.js:34361)
at Object.then (compiler.js:474)
at JitCompiler._compileModuleAndComponents (compiler.js:34359)
at JitCompiler.compileModuleAsync (compiler.js:34253)
at CompilerImpl.compileModuleAsync (platform-browser-dynamic.js:239)
at PlatformRef.bootstrapModule (core.js:5561)
at eval (main.ts:10)

Если я создам еще одну службу @Injectable(), вызывающую rest API через HttpClient, которую я введу внутрь RestErrorHandler, ошибки не будет. Почему это?




Ответы (2)


Просто дождитесь следующего выпуска angular или примените обходной путь, описанный в коммите, устраняющем эту проблему:

В настоящее время это возможно только путем внедрения инжектора и его использования для разрешения HttpClient во время запроса.

person JB Nizet    schedule 30.01.2018
comment
Спасибо. Если кому-то интересно, как это сделать в деталях: посмотрите мой ответ ниже. - person mdziob; 31.01.2018

Вот мое окончательное рабочее решение:

@Injectable()
export class RestErrorHandler implements HttpInterceptor {

private readonly ERROR_LOGGER_PATH: string = '/logger/errorEntry';

constructor(private injector: Injector, private restUtils: RestApiUtilsService) {}

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req).catch((errorReponse: HttpErrorResponse) => {
        return this.handleRestError(errorReponse, req, next);
    });
}

public handleRestError(error: HttpErrorResponse, req: HttpRequest<any>, next: HttpHandler): ErrorObservable {
    let errorMessage = this.prepareErrorMessage(error);
    let entry = this.prepareEntry(errorMessage);
    if (!this.http) this.http = this.injector.get(HttpClient);
    this.http.post(this.restUtils.getUrl(this.ERROR_LOGGER_PATH), JSON.stringify(entry), this.restUtils.jsonResponseRequestOptions()).subscribe();
    return Observable.throw(error);
}
}
person mdziob    schedule 31.01.2018