我在 Angular 2 中编写了两个服务。其中之一是一个基本的、自定义的 Http
类,其中包含一些自定义功能(目前看起来很基本,但它将不断扩展):
ServerComms.ts
import {Injectable} from 'angular2/core';
import {Http} from 'angular2/http';
@Injectable()
export class ServerComms {
private url = 'myservice.com/service/';
constructor (public http: Http) {
// do nothing
}
get(options) {
var req = http.get('https://' + options.name + url);
if (options.timout) {
req.timeout(options.timeout);
}
return req;
}
}
另一个类,TicketService
利用上面的此类,并调用服务中的方法之一。定义如下:
TicketService.ts
import {Injectable} from 'angular2/core';
import {ServerComms} from './ServerComms';
@Injectable()
export class TicketService {
constructor (private serverComms: ServerComms) {
// do nothing
}
getTickets() {
serverComms.get({
name: 'mycompany',
timeout: 15000
})
.subscribe(data => console.log(data));
}
}
但是,每当我尝试此操作时,我都会收到以下错误:
"No provider for ServerComms! (App -> TicketService -> ServerComms)"
我不明白为什么?我当然不需要注入(inject)每个其他服务所依赖的每个服务吗?这会变得相当乏味吗?这在 Angular 1.x 中是可以实现的 - 我如何在 Angular 2 中实现同样的效果?
这是正确的方法吗?
最佳答案
简而言之,由于注入(inject)器是在组件级别定义的,因此发起调用服务的组件必须看到相应的提供者。第一个(直接调用),但也间接调用另一个(由前一个服务调用)。
我们来举个例子。我有以下应用程序:
组件
AppComponent
:我的应用程序的主要组件,在bootstrap
中创建 Angular2 应用程序时提供。功能@Component({ selector: 'my-app', template: ` <child></child> `, (...) directives: [ ChildComponent ] }) export class AppComponent { }
组件
ChildComponent
:将在AppComponent
中使用的子组件组件@Component({ selector: 'child', template: ` {{data | json}}<br/> <a href="#" (click)="getData()">Get data</a> `, (...) }) export class ChildComponent { constructor(service1:Service1) { this.service1 = service1; } getData() { this.data = this.service1.getData(); return false; } }
两项服务,
Service1
和Service2
:Service1
由ChildComponent
使用和Service2
通过Service1
<小时/>@Injectable() export class Service1 { constructor(service2:Service2) { this.service2 = service2; } getData() { return this.service2.getData(); } }
@Injectable() export class Service2 { getData() { return [ { message: 'message1' }, { message: 'message2' } ]; } }
以下是所有这些元素及其关系的概述:
Application
|
AppComponent
|
ChildComponent
getData() --- Service1 --- Service2
在这样的应用程序中,我们有三个注入(inject)器:
- 可以使用
bootstrap
的第二个参数进行配置的应用程序注入(inject)器功能 AppComponent
可以使用providers
配置注入(inject)器该组件的属性。它可以“查看”应用程序注入(inject)器中定义的元素。这意味着如果在此提供程序中找不到提供程序,它将自动在该父注入(inject)器中查找。如果后者没有找到,则会抛出“未找到提供者”错误。ChildComponent
喷射器将遵循与AppComponent
相同的规则一。要注入(inject)为组件执行的注入(inject)链中涉及的元素,将首先在此注入(inject)器中查找提供程序,然后在AppComponent
中查找提供程序。第一个,最后是应用程序中的一个。
这意味着当尝试注入(inject)Service1
时进入ChildComponent
构造函数中,Angular2 将查看 ChildComponent
注入(inject)器,然后进入AppComponent
一,最后进入应用程序一。
自 Service2
需要注入(inject)Service1
,将进行相同的分辨率处理:ChildComponent
喷油器,AppComponent
一和应用一。
这意味着Service1
和Service2
可以根据您的需要使用providers
在每个级别指定组件的属性和 bootstrap
的第二个参数应用程序注入(inject)器的函数。
这允许共享一组元素的依赖关系实例:
- 如果您在应用程序级别定义提供程序,则相应创建的实例将由整个应用程序(所有组件、所有服务……)共享。
- 如果您在组件级别定义提供程序,则该实例将由组件本身、其子组件以及依赖链中涉及的所有“服务”共享。
所以它非常强大,您可以根据自己的需要自由地进行组织。
这是相应的 plunkr,您可以使用它:https://plnkr.co/edit/PsySVcX6OKtD3A9TuAEw?p=preview .
Angular2 文档中的此链接可以帮助您:https://angular.io/docs/ts/latest/guide/hierarchical-dependency-injection.html .
关于javascript - Angular 2 - 服务 - 来自另一个服务的依赖注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36651739/