Why is my service (this.loggerService) undefined in my DataHandlerService when it has been injected? I thought dependency injection took care of this. My loggerService works in other services. Please help me realize where I am going wrong. My DataHandlerService code below:
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { LoggerService } from './logger.service';
@Injectable()
export class DataHandlerService
{
constructor(private loggerService: LoggerService)
{
}
extractData(res: Response)
{
let body = res.json();
return body || {};
}
handleHttpError(error: any)
{
let errMsg = (error.message) ? error.message : error.status ? `${error.status} - ${error.statusText}` : 'Server error';
if (errMsg && this.loggerService) //Why is this.loggerService always undefined?
{
this.loggerService.error(errMsg);
}
return Observable.throw(errMsg);
}
}
My LoggerService code below:
import { Injectable } from '@angular/core';
import { Http, Headers, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { ConfigurationService } from './configuration.service';
@Injectable()
export class LoggerService
{
constructor(private http: Http, private configurationService: ConfigurationService)
{
}
public fatal(msg: string)
{
if (msg)
{
this.log(msg, "Fatal");
}
}
public debug(msg: string)
{
if (msg)
{
this.log(msg, "Debug");
}
}
public info(msg: string)
{
if (msg)
{
this.log(msg, "Info");
}
}
public warn(msg: string)
{
if (msg)
{
this.log(msg, "Warn");
}
}
public error(msg: string)
{
if (msg)
{
this.log(msg, "Error");
}
}
private log(msg: string, logLevel: string)
{
if (msg && logLevel && this.configurationService && this.configurationService.coreSettings)
{
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Accept', 'application/json');
let loggingInfo: LoggingInfo = { "message": msg, "logLevel": logLevel, "sourceName": "CoreIV", "logDirectory": this.configurationService.coreSettings.logDirectory };
this.http.post(this.configurationService.coreSettings.logbookUrl + "/rest/LogMessage", { loggingInfo }, { headers: headers })
.toPromise()
.then(res => this.extractData(res))
.catch(err => this.handleHttpError(err));
}
}
private extractData(res: Response)
{
let body = res.json();
return body || {};
}
private handleHttpError(error: any)
{
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
return Observable.throw(errMsg);
}
}
export interface LoggingInfo
{
message: string,
logLevel: string,
sourceName: string,
logDirectory: string
}
My App.Module code below:
import { NgModule, APP_INITIALIZER, ErrorHandler } from '@angular/core';
import { LocationStrategy, HashLocationStrategy } from '@angular/common';
import { HttpModule, JsonpModule, Jsonp } from '@angular/http';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, FormGroup, FormControl, ReactiveFormsModule } from '@angular/forms';
import { routing, appRoutingProviders } from './app.routing';
import { AppConfig } from './app.config';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { AppErrorHandler, LOGGING_ERROR_HANDLER_OPTIONS, LOGGING_ERROR_HANDLER_PROVIDERS } from './app.error-handler';
import { AppService } from './app.service';
import { ConfigurationService } from './shared/services/configuration.service';
import { DataHandlerService } from './shared/services/data-handler.service';
import { LoggerService } from './shared/services/logger.service';
import { AuthGuard } from './auth-guard.service';
export function init_app(appConfig: AppConfig, configurationService: ConfigurationService, loggerService: LoggerService)
{
// Do initiating of services that are required before app loads
// NOTE: this factory needs to return a function (that then returns a promise)
return appConfig.load()
.then((res) =>
{
configurationService.coreSettings = appConfig.config;
})
.catch((err) =>
{
loggerService.error(err);
});
}
@NgModule({
imports: [
BrowserModule,
FormsModule,
routing,
HttpModule,
JsonpModule
],
exports: [
],
declarations: [
HomeComponent,
AppComponent
],
providers: [
HttpModule,
ConfigurationService,
LoggerService,
{ provide: LocationStrategy, useClass: HashLocationStrategy },
LOGGING_ERROR_HANDLER_PROVIDERS,
{
provide: LOGGING_ERROR_HANDLER_OPTIONS,
useValue: {
rethrowError: false,
unwrapError: true
}
},
appRoutingProviders,
AuthGuard,
DataHandlerService,
AppConfig,
{
provide: APP_INITIALIZER,
useFactory: init_app,
deps: [AppConfig, ConfigurationService, LoggerService],
multi: false
}
],
bootstrap: [AppComponent, appRoutingProviders]
})
export class AppModule
{
constructor(private httpModule: HttpModule)
{
}
}
The @Injectable() decorator defines a class as a service in Angular and allows Angular to inject it into a component as a dependency. Likewise, the @Injectable() decorator indicates that a component, class, pipe, or NgModule has a dependency on a service.
Dependency injection, or DI, is one of the fundamental concepts in Angular. DI is wired into the Angular framework and allows classes with Angular decorators, such as Components, Directives, Pipes, and Injectables, to configure dependencies that they need.
@Injectable() lets Angular know that a class can be used with the dependency injector. @Injectable() is not strictly required if the class has other Angular decorators on it or does not have any dependencies.
This is termed as IOC(Inversion of Control) where control is being inverted to the external entity. Angular offers such a system that helps not only to register but also to instantiate component dependencies.
I found out the solution to this issue. The answer in the post angular 2 - Injected service in http error handler pointed me in the right direction. I was using the following:
.map(this.dataHandler.extractData)
.catch(this.dataHandler.handleHttpError);
but should use:
.map(res => this.dataHandler.extractData(res))
.catch(err => this.dataHandler.handleHttpError(err));
For some reason the lambdas are needed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With