簡體   English   中英

Angular 2-服務-來自另一個服務的依賴項注入

[英]Angular 2 - service - dependency injection from another service

我已經在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利用上面的此類,並調用服務中的方法之一。 定義如下:

票務服務

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)"

我不理解為什么? 當然,我不需要注入彼此依賴的每項服務嗎? 這會變得很乏味嗎? 這在Angular 1.x中是可以實現的-如何在Angular 2中實現相同的目標?

這是正確的方法嗎?

簡而言之,由於注入器是在組件級別定義的,因此發起呼叫服務的組件必須查看相應的提供者。 第一個(直接調用),但另一個間接調用(由先前的服務調用)。

讓我們取樣。 我有以下應用程序:

  • 組件AppComponent :在bootstrap函數中創建Angular2應用程序時提供的應用程序的主要組件

     @Component({ selector: 'my-app', template: ` <child></child> `, (...) directives: [ ChildComponent ] }) export class AppComponent { } 
  • 組件ChildComponent :將在AppComponent組件內使用的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; } } 
  • 兩個服務, Service1Service2Service1時使用的ChildComponentService2通過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

在這種應用中,我們有三個噴射器:

  • 可以使用bootstrap功能的第二個參數配置的應用程序注入器
  • 可以使用此組件的providers屬性配置的AppComponent注入器。 它可以“看到”在應用程序注入器中定義的元素。 這意味着,如果在此提供程序中找不到提供程序,則會自動在此父注入器中查找。 如果在后者中未找到,將引發“未找到提供程序”錯誤。
  • ChildComponent注入器將遵循與AppComponent相同的規則。 為了注入在組件中執行的注入鏈中涉及的元素,將首先在該注入器中尋找提供程序,然后在AppComponent者,最后在應用程序中尋找提供者。

這意味着,當嘗試將Service1注入ChildComponent構造函數時,Angular2會尋找ChildComponent注入器,然后是AppComponent ,最后是應用程序。

由於Service2需要被注入到Service1 ,相同分辨率的處理會做到: ChildComponent注射器, AppComponent一個應用程序之一。

這意味着可以使用組件的providers屬性和應用程序注入程序的bootstrap函數的第二個參數,根據您的需要在每個級別上指定Service1Service2

這允許共享一組元素的依賴項實例:

  • 如果您在應用程序級別定義提供程序,則相應的創建實例將由整個應用程序共享(所有組件,所有服務等)。
  • 如果您在組件級別定義提供程序,則實例將由組件本身,其子組件以及依賴關系鏈中涉及的所有“服務”共享。

因此它非常強大,您可以根據自己的需要和需要自由組織。

這是相應的plunkr,因此您可以使用它: https ://plnkr.co/edit/PsySVcX6OKtD3A9TuAEw?p=preview。

Angular2文檔中的此鏈接可以為您提供幫助: https ://angular.io/docs/ts/latest/guide/hierarchical-dependency-injection.html。

當然可以。

在Angular2中,有多個注入器。 注入器使用組件的providers數組進行配置。 當組件具有providers數組時,將在樹中的該點創建注入器。 當組件,指令和服務需要解決它們之間的依賴關系時,它們會查詢注入器樹以找到它們。 因此,我們需要使用提供程序配置該樹。

從概念上講,我喜歡認為有一個注入器樹覆蓋了組件樹,但它比組件樹稀疏。

同樣,從概念上講,我們必須配置此注入器樹,以便在樹中的適當位置“提供”依賴項。 Angular 2沒有創建單獨的樹,而是重用了組件樹來做到這一點。 因此,即使感覺像我們正在配置對組件樹的依賴關系,我還是認為我正在配置對注入器樹的依賴關系(它恰好覆蓋了組件樹,因此我必須使用組件對其進行配置)。

像泥一樣清澈?

Angular 2擁有注入器樹的原因是允許非單一服務-即能夠在注入器樹中的不同點創建特定服務的多個實例的能力。 如果要使用類似於Angular 1的功能(僅單例服務),請在根組件中提供所有服務。


設計您的應用程序, 然后返回並配置注入器樹(使用組件)。 我就是這么想的。 如果您在另一個項目中重用組件,則很有可能需要更改providers數組,因為新項目可能需要不同的注入器樹。

好吧,我想您應該在全球范圍內提供兩種服務:

bootstrap(App, [service1, service2]);

或提供給使用它們的組件:

@Component({providers: [service1, service2]})

@Injectable裝飾器添加必要的元數據來跟蹤依賴關系,但不提供它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM