2016-02-10 37 views
11

Hãy nói rằng chúng tôi có một phần gọi là Comp và hai nhà cung cấp @Injectable gọi P1P2.cung cấp Tiêm vào một nhà cung cấp góc 2

P1 cần một phiên bản P2.

P1 được tiêm vào Comp

Đó là làm việc một cách hoàn hảo nếu tôi tuyên bố cả hai nhà cung cấp trên Comp, như thế:

@Component ({ 
    providers: [P1, P2] 
}) 
export class Comp { ... } 

Bây giờ những gì tôi muốn làm là để khai báo rằng P1 cần P2 trực tiếp bên trong P1:

@Component ({ 
    providers: [P1] 
}) 
export class Comp { ... } 


@Injectable(/** Inject P2 here **/) 
export class P1 { ... } 

Cảm ơn sự giúp đỡ của bạn.

Trả lời

8

Thực tế, các bộ phun chỉ có thể được cấu hình mức thành phần hoặc khi khởi động ứng dụng.

Khi bạn đặt nhà cung cấp cấp thành phần, mọi lớp học liên quan đến quá trình xử lý sẽ có quyền truy cập vào các nhà cung cấp này: các thành phần phụ, dịch vụ. Nhưng bạn không thể tự định cấu hình nhà cung cấp dịch vụ.

Nếu bạn định cấu hình nhà cung cấp ở cấp khởi động (khi gọi hàm bootstrap), tất cả các yếu tố trong ứng dụng sẽ có thể sử dụng các nhà cung cấp này.

Trong thực tế, bộ phận phụ thuộc của Angular2 sử dụng kim phun phân cấp. Điều này có nghĩa là nhà cung cấp không được tìm thấy ở một cấp độ, nó sẽ được tìm kiếm ở cấp độ trên và như vậy.

Dưới đây là một tổng quan về tất cả những yếu tố này và mối quan hệ đó:

Application 
(providers defined in bootstrap) 
    | 
AppComponent 
(providers defined in the providers attribute) 
    | 
ChildComponent 
(providers defined in the providers attribute) 
    getData()  --- Service1 --- Service2 

Để có thể sử dụng Service2 trong Service1, nhà cung cấp tương ứng phải được tìm thấy trong cây nhà cung cấp.

Trong ứng dụng như vậy, chúng tôi có ba kim phun:

  • Các vòi phun ứng dụng có thể được cấu hình bằng cách sử dụng tham số thứ hai của bootstrap chức năng
  • Các AppComponent phun có thể được cấu hình bằng cách sử dụng providers thuộc tính này thành phần. Nó có thể "nhìn thấy" các yếu tố được định nghĩa trong bộ phun ứng dụng. Điều này có nghĩa là nếu một nhà cung cấp không được tìm thấy trong nhà cung cấp này, nó sẽ được tự động tìm kiếm trong bộ tiêm phụ huynh này. Nếu không tìm thấy sau này, lỗi "không tìm thấy nhà cung cấp" sẽ bị ném.
  • Máy quét ChildComponent sẽ tuân thủ cùng một quy tắc so với AppComponent. Để chèn các phần tử liên quan đến chuỗi tiêm được thực thi forr thành phần, các nhà cung cấp sẽ được tìm kiếm đầu tiên trong bộ phun này, sau đó trong AppComponent và cuối cùng là trong ứng dụng.

Câu trả lời này có thể cung cấp cho bạn chi tiết hơn về các kim phun thứ bậc:

1

Injectables phụ thuộc hỗ trợ Tiêm theo cùng một cách mà các thành phần thực hiện, thông qua quá trình tạo hàm tạo.

@Injectable() 
export class P1 { 
    constructor(private p2: P2){} 
} 

Bạn có thể khai báo nó như một nhà cung cấp sẵn cho toàn bộ ứng dụng bằng cách thêm nó vào bootstrap

bootstrap(MyAppComponent, [P1, P2, ...]); 
+0

Nhưng bạn cần khai báo nó như một nhà cung cấp ở đâu đó .. thực sự câu hỏi là: Làm thế nào để khai báo nó như một nhà cung cấp bên trong trực tiếp bên trong nhà cung cấp –

+0

Đã chỉnh sửa để trả lời câu đó. – SnareChops

+0

Yea, nhưng tôi không muốn một singleton: ( –

3

Bạn có hai lựa chọn:

  1. Như đã đề cập trong câu trả lời khác , bạn phải đặt dịch vụ của mình vào mảng providers của thành phần, như bạn đã làm:

    providers: [P1, P2] 
    

    Và trong constructor P1 's chỉ tiêm nó:

    export class P1 { 
        constructor(private p2: P2){} 
    } 
    
  2. Nếu bạn không muốn đặt nó trong mảng providers, bạn có thể làm điều đó trong bootstrap phương pháp mà bootstraps thành phần chính của bạn:

    bootstrap(AppComponent, [P2]); 
    

Và một lần nữa, chỉ cần tiêm nó theo cùng một cách trong P1

Tôi không khuyên bạn nên sử dụng phiên bản thứ hai và những người sáng tạo của Angular 2 cũng không đề xuất nó. Nếu bạn muốn có một dịch vụ toàn cầu có sẵn ở khắp mọi nơi (trong các dịch vụ và các thành phần khác, chỉ cần đặt nó trong providers mảng của các thành phần gốc)

Nguồn: https://angular.io/docs/ts/latest/guide/dependency-injection.html

Chúng tôi phải cấu hình các vòi phun bằng cách đăng ký các nhà cung cấp tạo ra các dịch vụ mà chúng tôi cần trong ứng dụng của chúng tôi. Chúng tôi sẽ giải thích những gì các nhà cung cấp sau này trong chương này.Trước khi chúng tôi làm, chúng ta hãy xem một ví dụ về đăng ký cung cấp dịch vụ trong bootstrapping:

// Injecting services in bootstrap works but is discouraged

bootstrap(AppComponent, [HeroService]);

Các injector bây giờ biết về HeroService của chúng tôi. Một trường hợp của HeroService của chúng tôi sẽ có sẵn để tiêm trên toàn bộ ứng dụng của chúng tôi.

Tất nhiên chúng tôi không thể không tự hỏi về nhận xét đó nói rằng chúng tôi không được làm theo cách này. Nó sẽ hoạt động. Nó không chỉ là một cách thực hành tốt nhất. Tùy chọn nhà cung cấp dịch vụ khởi động được thiết kế để định cấu hình và ghi đè các dịch vụ được đăng ký trước của Angular.

Cách tiếp cận ưa thích là đăng ký nhà cung cấp ứng dụng trong các thành phần ứng dụng . Vì HeroService sẽ được sử dụng trong phạm vi khu vực tính năng của Anh hùng - và không nơi nào khác - nơi lý tưởng để đăng ký, nó nằm trong HeroesComponent cấp cao nhất.

1

Có một vấn đề mở cho rằng

https://github.com/angular/angular/issues/5622

Nó doesn' t nhìn quá khả năng điều này sẽ được thực hiện: -/

Hiện tại, các nhà cung cấp chỉ có thể được khai báo tại các thành phần/chỉ thị/đường ống và trong bootstrap(). Ngoài ra một hạn chế với các nhà cung cấp tại các thành phần/chỉ thị/đường ống là họ không thể bị ghi đè trong một cấu hình toàn cầu.

1

Bạn có thể làm điều đó theo cách này:

import {Injectable, Inject} from 'angular2/core'; 
import {Http, Response, Headers, RequestOptions} from 'angular2/http'; 
import {Observable} from 'rxjs/Rx'; 
import {P2} from '../p2/p2.service'; // path to P2 

@Injectable(/** Inject P2 here **/) 
export class P1 { 
    private _p2Service: P2 

    constructor(private http: Http) { 
    this._p2Service = new P2(this.http); 
    } 

    getProcessedP2Data() { 
    ... create your Rx obserwable here, read async data from P2, prcess them, and return obserwable (subscriable) object 
    } 
} 

Bạn cũng có thể sẽ cần phải tạo ra RxJS của riêng bạn obserwable để trả lại dữ liệu chế biến từ P2. Nhìn vào đây để biết chi tiết: https://egghead.io/lessons/rxjs-creating-an-observable

+0

Tuyệt vời !! Instantiating thủ công hiện các trick! –

Các vấn đề liên quan