【问题标题】:Angular 2 Injected Service is undefinedAngular 2 注入服务未定义
【发布时间】:2017-08-14 20:59:13
【问题描述】:

为什么我的服务 (this.loggerService) 被注入后在我的 DataHandlerService 中未定义?我认为依赖注入可以解决这个问题。我的 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)
{

}
}

【问题讨论】:

  • 您在哪里以及如何提供DataHandlerServiceLoggerService
  • 您好 Günter,我已编辑帖子以包含我的 app.module.ts,这是我提供这些服务的地方。
  • 找不到任何可能有问题的地方:-/

标签: angular dependency-injection angular-services


【解决方案1】:

我找到了解决这个问题的方法。 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));

由于某种原因需要 lambda。

【讨论】:

  • 为我省了很多苦头!
  • 如果你不使用 lambda,在“extractData”和“handleHttpError”中,“this”上下文将指向其他地方。为了让它工作,你可以绑定当前上下文:.map(this.dataHandler.extractData.bind(this).catch(this.dataHandler.handleHttpError.bind(this));
  • 仍然是 Angular 5 中的解决方案。
  • 第一个调用忽略了类实例,而第二个则没有。这样做的原因是有道理的。
【解决方案2】:

即使答案正确且被接受,但还是想写下失败的原因以及另一种可能的解决方案。

而不是写

.map(this.dataHandler.extractData)
.catch(this.dataHandler.handleHttpError);

你可以使用

.map(this.dataHandler.extractData.bind(this))
.catch(this.dataHandler.handleHttpError.bind(this));

失败的主要原因是this 根据执行上下文获取它的值,如果服务在setTimeoutsetInterval 中调用,在我的例子中this 的值是@987654327 @(由于严格模式 - 否则它将是 window 对象)。通过使用.bind,您可以显式提供this(组件类对象)的值。

【讨论】:

  • 确实没有这个解释。我建议编辑接受的答案,以使其他用户可以访问。
【解决方案3】:

当我无法在主应用程序模块中导入服务并将其列在提供程序部分时,就会发生这种情况

// in app.module.ts     
import { LoggerService } from './logger.service';
...
@NgModule({
...
  providers: [
    LoggerService,

【讨论】:

  • 嗨罗伯特,我已经编辑了帖子以包含我的 app.module.ts
猜你喜欢
  • 1970-01-01
  • 2019-08-09
  • 2016-03-25
  • 2016-03-30
  • 2016-06-20
  • 2017-08-24
  • 2016-07-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多