2

I am trying to implement a global handler to manage HTTP errors in Angular2. Going through few reference: http://restlet.com/blog/2016/04/18/interacting-efficiently-with-a-restful-service-with-angular2-and-rxjs-part-3/ and https://blog.tomasandtomas.com/angular-2-http-interceptors-7e2d74b7f14e#.nxgxijnqu , I made the following:

--------------------------------------------------------------------
// Logger service - which will be able to send the error to server or log to console
import { Http } from '@angular/http';
import { Injectable } from '@angular/core';
import { Response } from '@angular/http';

@Injectable()
export class ErrorLogService {
    public logError(error: any): void {
       // custom error handling here
       console.log(error);
    }
}
--------------------------------------------------------------------
// This is the Custom HTTP that extends Http module
import { Injectable } from '@angular/core';
import { Http, ConnectionBackend, Request, RequestOptions, RequestOptionsArgs } from '@angular/http';
import { ErrorLogService } from '../ErrorHandling/error.log.service';
import { Observable } from 'rxjs/Rx';

@Injectable()
export class CustomHttp extends Http {    

    constructor(_backEnd: ConnectionBackend,
        defaultOptions: RequestOptions, private errorLogService: ErrorLogService) {
        super(_backEnd, defaultOptions);        
    }    
    get(url: string, options?: RequestOptionsArgs): Observable<any> {
        return super.request(url, options)
        .catch((error: any): any => {
            this.errorLogService.logError(error);
            return Observable.empty();
        })            
        .finally(() => {
            console.log('Done');
        });
    }    
}

--------------------------------------------------------------------
// This is the service that call the api to get data.
import { Http, Response } from '@angular/http';
import { Injectable } from '@angular/core';
import { IAsset } from './asset';
import { AppSettings } from '../app.settings';


import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/toPromise';

@Injectable()
export class AssetService {
    private _cid = 1234;
    private _total = 774;
    private _pageIndex = 1;

    constructor(private _http: Http) { }

    getAssets(pageIndex: number): Promise<IAsset[]> {
        this._pageIndex = pageIndex;
        let _assetApi = `${AppSettings.GET_CONFIG('assets')}?1cid=${this._cid}&count=${this._total}&index=${this._pageIndex}`;


        return this._http.get(_assetApi)
            .toPromise()
            .then(response => response.json() as IAsset[]);

    }    
}

--------------------------------------------------------------------
//This is how custom Http is injected in the app module
    import { NgModule, APP_INITIALIZER, ErrorHandler } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    import { HttpModule } from '@angular/http';
    import { Http, XHRBackend, RequestOptions } from '@angular/http';

    import { AppComponent } from './app.component';
    import { WelcomeComponent } from './home/welcome.component';
    import { ProductModule } from './products/product.module';

    import { AppRoutingModule } from './app.routing.module';
    import { ErrorLogService } from './shared/ErrorHandling/error.log.service';
    import { CustomHttp } from './shared/Http/custom.http.service';

    @NgModule({
    imports: [
        BrowserModule,
        HttpModule,
        AppRoutingModule,
        ProductModule
    ],
    declarations: [
        AppComponent,
        WelcomeComponent
    ],
    providers: [
        ConfigService,
        AuthService,    
        ErrorLogService,
        {
        provide: Http,
        useFactory: (backend: XHRBackend, defaultOptions: RequestOptions, _errorLogService: ErrorLogService) => {
            return new CustomHttp(backend, defaultOptions, _errorLogService);
        },
        deps: [XHRBackend, RequestOptions]
        }
    ],
    bootstrap: [AppComponent],

    })
    export class AppModule { }

Now the problem is that I anytime there is a 500 internal server error on my data service, it is caught by by the CustomHttp, but the this.errorLogService.logError(error); >> errorLogService is undefined and does not invoke the logError on it.

I am using the Angular 2.0.0.0.

Any pointers on this issue? - Thanks.

1 Answer 1

3

You need to add ErrorLogService to CustomHttp's provider deps:

providers: [
    ConfigService,
    AuthService,    
    ErrorLogService,
    {
    provide: Http,
    useFactory: (backend: XHRBackend, defaultOptions: RequestOptions, _errorLogService: ErrorLogService) => {
        return new CustomHttp(backend, defaultOptions, _errorLogService);
    },
    deps: [XHRBackend, RequestOptions, ErrorLogService] <-- this
    }
],
Sign up to request clarification or add additional context in comments.

4 Comments

Tried that before and ran into this error: Cannot instantiate cyclic dependency! Http: in NgModule AppModule
@SrirajM Remove ErrorLogService from AppModule's providers, just leave it in deps.
Found the issue why its coming up even after i leave it dep. In my ErrorLogService there is a way to log the error on server using http. So the moment i add a constructor : constructor(private _http: Http) { }, this cyclic dependency comes back.
Thanks for the help - anyway I could send this error to server? and handle it globally?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.