user348173
user348173

Reputation: 9288

One service throw exception when I use Injector.get()

I have a service for making http requests. Let's consider one method:

export class JsonApiService {
 constructor(private http: Http, private localStorageService: LocalStorageService) { }

      public get(url, params?, requestOptions: any = {}): Observable<any> {        
        const options = this.buildRequestOptions(requestOptions);
        const fullUrl = this.buildUrl(url);
        const urlWithQuery = this.addQueryParams(fullUrl, params);
        return this.http.get(urlWithQuery, options)         
          .map(this.extractData)
          .catch((e) => this.handleError(e));
      }
}

As yoy can see I use catch for caching errors. This is the handleError function:

private handleError(error: any): Observable<any> {
    let body  = error.json ? error.json() : '';
    if (!environment.production) {
      console.warn(error);
    }
    this.onError.next(body);       
    if(error.status === 0) {
      body.message = 'Can\'t connect to the server.';
    }

    return Observable.throw(body);
  }

Pretty standard code for this task. Now, I need to handle one specific server error response. The specific error json contains one field checkIntegration. So, I want to check error and if it contains this field. If yes then do some custom logic. I don't want to put this logic to JsonApiService itself, because I want to reuse this service from project to project and I actually do . I have been using it for the last 3 projects without any modification.

So, I wrote my custom error handler:

export class ErrorHandlerService extends ErrorHandler {
  constructor(private injector: Injector) {
    super(true);

    let jsonApiService = this.injector.get(JsonApiService);
    jsonApiService.onError.subscribe((err) => {
      this.handleError(err);
    })
  }

  ...
}

As you can see I use onError. It's just Subject. But, I have error on application startup: Cannot read property 'notifyOptions' of undefined ; Zone: <root> ; Task: Promise.then ; Value: TypeError: Cannot read property 'notifyOptions' of undefined at new LocalStorageService (local-storage.service.js:34)

The error is thrown inside local-storage.service. It's not mine service, but I inject this service to JsonApiService. I believe not all services are created when I use injector in my handler. Any ideas?

PS. I use the following library for local storage: https://github.com/phenomnomnominal/angular-2-local-storage/blob/master/src/local-storage.service.ts#L38

Upvotes: 0

Views: 493

Answers (1)

Estus Flask
Estus Flask

Reputation: 222720

In the code above LocalStorageService likely wasn't configured properly, because said property originates in configuration provider.

The error is thrown on JsonApiService instantiation, it will prevent the provider from functioning normally. There's no point in handling the error with onError because the error is thrown long before handleError.

It should be caught in the place where problem provider is instantiated:

export class JsonApiService {
 private localStorageService?: LocalStorageService;
 constructor(private http: Http, private injector: Injector) { }
   try {
     this.localStorageService = injector.get(LocalStorageService);
   } catch (err) {
     ...
   }

But the proper solution is to address the cause of the problem in the first place.

Upvotes: 1

Related Questions