如何在Angular 5中使用服务进行依赖项注入?

时间:2018-11-12 00:50:56

标签: angular service dependency-injection

如何使用服务进行依赖项注入?

我收到打字稿通知:

  

[角度]不能解析LandingComponent中的所有参数   landing.component.ts:   ([object Object],?)。


更新

我不应该像这样在构造函数中使用LangService:

  

private _langService:LangService;

因为LangService是一个实现。在实际情况下,几乎没有像LangMockedSerives,langService_01,langService_02这样的实现。因此,着陆组件应该不了解有关实现的知识,并且只能使用接口。


服务及其界面

export interface ILangService {
}

export class LangService implements ILangService {
}

组件

import { ILangService } from '../../services/Ilang.service';

@Component({
    selector: 'app-landing',
    templateUrl: './landing.component.html',
    styleUrls: ['./landing.component.less']
})

export class LandingComponent {
    private langService: ILangService
    constructor(
        private http: HttpClient,
        _langService: ILangService;
    ) {
        this._langService = langService;
    }
}

app.module.ts

import { ILangService } from './services/Ilang.service';
import { LangService } from './services/Lang.service';

@NgModule({
  declarations: [
    AppComponent,
    LandingComponent,
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    RouterModule.forRoot([
      { path: '', component: LandingComponent },
    ], { useHash: false }),
  ],
  providers: [
    LangService
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

3 个答案:

答案 0 :(得分:0)

更新的答案

如果您想对同一服务使用不同的实现,则应创建一个InjectionToken<T>并在模块声明中为您的接口提供正确的实现。

接口-lang.service.ts

创建将由使用ILangService接口键入的注射器识别的注射令牌

export const LangService = new InjectionToken<ILangService>('LangService');

export interface ILangService { }

第一个模块-english.module.ts

EnglishLangService注入令牌提供LangService,其中EnglishLangService实现ILangService接口

import { LangService } from './services/lang.service';
import { EnglishLangService } from './services/english-lang.service';

@NgModule({
  declarations: [ LandingComponent ],
  providers: [
    { provide: LangService, useClass: EnglishLangService }
  ]
})
export class EnglishModule { }

第二个模块-french.module.ts

FrenchLangService注入令牌提供LangService,其中FrenchLangService实现ILangService接口

import { LangService } from './services/lang.service';
import { FrenchLangService } from './services/french-lang.service';

@NgModule({
  declarations: [ LandingComponent ],
  providers: [
    { provide: LangService, useClass: FrenchLangService }
  ]
})
export class FrenchModule { }

组件-Landing.component.ts

通过这种方式,您可以在组件中注入LangService,注入器将检索模块中提供的实现

import { LangService } from '../../services/lang.service';

@Component({
    selector: 'app-landing',
    templateUrl: './landing.component.html',
    styleUrls: ['./landing.component.less']
})
export class LandingComponent {
    constructor(
        private http: HttpClient,
        private langService: LangService,
    ) { }
}

测试-模拟-lang.service.ts

在测试时,您将能够以与在应用程序模块中提供正确实现相同的方式来提供模拟实现

import { LangService } from './services/lang.service';
import { MockLangService } from './services/mock-lang.service';

TestBed.configureTestingModule({
  providers: [
    { provide: LangService, useClass: MockLangService },
  ],
});

原始答案

您应该使用类而不是接口导入服务

import { LangService } from '../../services/lang.service';

@Component({
    selector: 'app-landing',
    templateUrl: './landing.component.html',
    styleUrls: ['./landing.component.less']
})
export class LandingComponent {
    constructor(
        private http: HttpClient,
        private langService: LangService;
    ) { }
}

也不要忘记在服务类声明上设置@Injectable()装饰器

import { Injectable } from '@angular/core';

@Injectable()
export class LangService implements ILangService { }

当然,您必须向模块提供服务

import { LangService } from './services/Lang.service';

@NgModule({
  declarations: [
    AppComponent,
    LandingComponent,
  ],
  imports: [ ... ],
  providers: [
    LangService
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

您可以在此处了解有关角度依赖注入的信息:https://angular.io/guide/dependency-injection

另一个用于高级服务声明的有趣链接:https://offering.solutions/blog/articles/2018/08/17/using-useclass-usefactory-usevalue-useexisting-with-treeshakable-providers-in-angular/

答案 1 :(得分:0)

service.ts

import { Injectable } from '@angular/core';
import { HttpClient, Response, RequestOptions, Headers } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';

export interface ILangService {
}

 @Injectable()   
export class LangService implements ILangService {

 constructor(private http: HttpClient) {  <-- httpclient for angular6
  }

getData(): Observable<any[]> {
return this.http.get('https://..../');
.map(this.extractData)
 .catch(this.handleError);
 }

private extractData(res: Response) {
const body = res.json();
return body || [];
}

private handleError(error: any) {
const errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg);
console.log('Error....!');
 return Observable.throw(errMsg);
}
}

组件:-

import { LangService } from '../../services/lang.service'; <-- Import sevice here

@Component({
selector: 'app-landing',
templateUrl: './landing.component.html',
styleUrls: ['./landing.component.less']
})

 export class LandingComponent {
constructor(
private http: HttpClient,
_langService: LangService  <--- service
) { }

ngOnInit() {
let thisx = this;
this._langService.getData().subscribe(
function (success) {
// alert here on success
alert (success);
},
 error => console.log('Getting Server Data Error :: ' + 
JSON.stringify(error)));
}
}

答案 2 :(得分:0)

LangService应该从app.module.ts提供程序中删除:

@NgModule({
  declarations: [
    AppComponent,
    LandingComponent,
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    RouterModule.forRoot([
      { path: '', component: LandingComponent },
    ], { useHash: false }),
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

并且应该将接口添加到组件中的提供程序:

import { LangService } from '../../services/Lang.service';
import { ILangService } from '../../services/ILang.service';

@Component({
    selector: 'app-landing',
    templateUrl: './landing.component.html',
    styleUrls: ['./landing.component.less'],
    providers: [
        { provide: ILangService, useClass: LangService }
    ]
})

export class LandingComponent {
    private langService: ILangService
    constructor(
        private http: HttpClient,
        _langService: ILangService;
    ) {
        this._langService = langService;
    }
}