为什么注入时我的DataHandlerService中的服务(this.loggerService)未定义?我认为依赖注入可以解决这个问题。我的loggerService适用于其他服务。请帮我意识到我哪里出错了。我的DataHandlerService代码如下:
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);
}
}
我的LoggerService代码如下:
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
}
我的App.Module代码如下:
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)
{
}
}
答案 0 :(得分:33)
我找到了解决这个问题的方法。帖子angular 2 - Injected service in http error handler中的答案指出了我正确的方向。我使用以下内容:
.map(this.dataHandler.extractData)
.catch(this.dataHandler.handleHttpError);
但应该使用:
.map(res => this.dataHandler.extractData(res))
.catch(err => this.dataHandler.handleHttpError(err));
由于某些原因,需要使用lambdas。
答案 1 :(得分:3)
当我无法在主应用程序模块中导入服务并将其列在提供程序部分时,就会发生这种情况
// in app.module.ts
import { LoggerService } from './logger.service';
...
@NgModule({
...
providers: [
LoggerService,
答案 2 :(得分:0)
即使答案是正确的并被接受,也要写下失败的原因以及另一种可能的解决方案。
代替写作
.map(this.dataHandler.extractData)
.catch(this.dataHandler.handleHttpError);
您可以使用
.map(this.dataHandler.extractData.bind(this))
.catch(this.dataHandler.handleHttpError.bind(this));
失败的主要原因是this
根据执行上下文确定其值,并且如果在setTimeout
或setInterval
中调用了该服务,例如我的情况this
为undefined
(由于严格模式-否则它将是window
对象)。通过使用.bind
,您可以显式提供this
的值(组件类对象)。