Làm cách nào để tạo một dịch vụ đơn lẻ trong Angular 2?


142

Tôi đã đọc rằng tiêm khi bootstrapping nên có tất cả trẻ em chia sẻ cùng một thể hiện, nhưng các thành phần chính và tiêu đề của tôi (ứng dụng chính bao gồm thành phần tiêu đề và ổ cắm bộ định tuyến) mỗi loại có một phiên bản dịch vụ riêng của tôi.

Tôi có một Dịch vụ FacebookS mà tôi sử dụng để thực hiện các cuộc gọi đến api javascript facebook và Dịch vụ người dùng sử dụng Dịch vụ FacebookS. Đây là bootstrap của tôi:

bootstrap(MainAppComponent, [ROUTER_PROVIDERS, UserService, FacebookService]);

Từ nhật ký của tôi, có vẻ như cuộc gọi bootstrap kết thúc, sau đó tôi thấy FacebookService sau đó UserService được tạo trước khi mã trong mỗi hàm tạo chạy, MainAppComponent, HeaderComponent và DefaultComponent:

nhập mô tả hình ảnh ở đây


8
Bạn có chắc là bạn chưa thêm UserServiceFacebookServicevào providersbất cứ nơi nào khác không?
Günter Zöchbauer

Câu trả lời:


132

Jason hoàn toàn đúng! Nó gây ra bởi cách tiêm phụ thuộc hoạt động. Nó dựa trên kim phun phân cấp.

Có một số kim phun trong ứng dụng Angular2:

  • Cái gốc bạn cấu hình khi bootstrapping ứng dụng của bạn
  • Một kim phun cho mỗi thành phần. Nếu bạn sử dụng một thành phần bên trong một thành phần khác. Người tiêm thành phần là con của thành phần cha mẹ. Thành phần ứng dụng (thành phần bạn chỉ định khi tăng cường ứng dụng của bạn) có trình tiêm gốc là cha mẹ).

Khi Angular2 cố gắng tiêm một cái gì đó vào hàm tạo thành phần:

  • Nó nhìn vào kim phun liên kết với các thành phần. Nếu có một kết hợp, nó sẽ sử dụng nó để lấy ví dụ tương ứng. Trường hợp này được tạo ra một cách lười biếng và là một đơn vị cho người tiêm này.
  • Nếu không có nhà cung cấp ở cấp độ này, nó sẽ xem xét công cụ tiêm cha mẹ (v.v.).

Vì vậy, nếu bạn muốn có một singleton cho toàn bộ ứng dụng, bạn cần phải có nhà cung cấp được xác định ở cấp độ của trình tiêm gốc hoặc trình tiêm thành phần ứng dụng.

Nhưng Angular2 sẽ nhìn vào cây kim phun từ phía dưới. Điều này có nghĩa là nhà cung cấp ở mức thấp nhất sẽ được sử dụng và phạm vi của trường hợp liên quan sẽ là mức này.

Xem câu hỏi này để biết thêm chi tiết:


1
Cảm ơn, điều đó giải thích nó tốt. Nó chỉ là phản trực giác đối với tôi bởi vì điều đó phá vỡ mô hình thành phần khép kín của góc 2. Vì vậy, giả sử tôi đang tạo một thư viện các thành phần cho Facebook, nhưng tôi muốn tất cả chúng sử dụng một dịch vụ đơn lẻ. Có thể có một thành phần để hiển thị ảnh đại diện của người dùng đã đăng nhập và một thành phần khác để đăng. Ứng dụng sử dụng các thành phần đó phải bao gồm dịch vụ Facebook với tư cách là nhà cung cấp ngay cả khi ứng dụng đó không sử dụng chính dịch vụ đó? Tôi chỉ có thể trả lại một dịch vụ bằng phương thức 'getInstance ()' quản lý đơn vị dịch vụ thực sự ...
Jason Goemaat

@tThierryTemplier Làm thế nào tôi sẽ làm điều ngược lại, tôi có một lớp dịch vụ chung tôi muốn tiêm trong nhiều thành phần nhưng nhanh chóng một trường hợp mới mỗi thời gian (các nhà cung cấp / options chỉ là vụ phải được chấp nhận và loại bỏ trong phiên bản tiếp theo)
Boban Stojanovski

Xin lỗi vì đã quá ngu ngốc nhưng đối với tôi, làm thế nào để bạn tạo ra một dịch vụ đơn lẻ, bạn có thể giải thích chi tiết hơn không?
gyozo kudor

Vì vậy, để làm việc với một phiên bản duy nhất của dịch vụ, nó có nên được khai báo là nhà cung cấp trong app.module.ts hoặc trong app.component.ts không?
dùng1767316

Khai báo mỗi dịch vụ chỉ trong app.module.ts, đã thực hiện công việc cho tôi.
dùng1767316

142

Cập nhật (Góc 6 +)

Cách được đề xuất để tạo một dịch vụ đơn lẻ đã thay đổi. Hiện tại nên chỉ định trong trình @Injectabletrang trí trên dịch vụ rằng nó sẽ được cung cấp trong 'root'. Điều này rất có ý nghĩa với tôi và không cần phải liệt kê tất cả các dịch vụ được cung cấp trong các mô-đun của bạn nữa. Bạn chỉ cần nhập các dịch vụ khi bạn cần và họ tự đăng ký ở nơi thích hợp. Bạn cũng có thể chỉ định một mô-đun để nó sẽ chỉ được cung cấp nếu mô-đun được nhập.

@Injectable({
  providedIn: 'root',
})
export class ApiService {
}

Cập nhật (Góc 2)

Với NgModule, cách để làm điều đó bây giờ tôi nghĩ là tạo ra một 'CoreModule' với lớp dịch vụ của bạn trong đó và liệt kê dịch vụ trong các nhà cung cấp của mô-đun. Sau đó, bạn nhập mô-đun lõi trong mô-đun ứng dụng chính của mình, nó sẽ cung cấp một thể hiện cho bất kỳ đứa trẻ nào yêu cầu lớp đó trong các hàm tạo của chúng:

CoreModule.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ApiService } from './api.service';

@NgModule({
    imports: [
        CommonModule
    ],
    exports: [ // components that we want to make available
    ],
    declarations: [ // components for use in THIS module
    ],
    providers: [ // singleton services
        ApiService,
    ]
})
export class CoreModule { }

AppModule.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AppComponent } from './app.component';
import { CoreModule } from './core/core.module';

@NgModule({
    declarations: [ AppComponent ],
    imports: [
        CommonModule,
        CoreModule // will provide ApiService
    ],
    providers: [],
    bootstrap: [ AppComponent ]
})
export class AppModule { }

Câu trả lời gốc

Nếu bạn liệt kê một nhà cung cấp bootstrap(), bạn không cần liệt kê chúng trong trang trí thành phần của bạn:

import { ApiService } from '../core/api-service';

@Component({
    selector: 'main-app',
    templateUrl: '/views/main-app.html',
    // DO NOT LIST PROVIDERS HERE IF THEY ARE IN bootstrap()!
    // (unless you want a new instance)
    //providers: [ApiService]
})
export class MainAppComponent {
    constructor(private api: ApiService) {}
}

Trong thực tế, việc liệt kê lớp của bạn trong 'nhà cung cấp sẽ tạo ra một thể hiện mới của nó, nếu bất kỳ thành phần cha mẹ nào đã liệt kê nó thì trẻ em không cần và nếu chúng làm thì chúng sẽ có một thể hiện mới.


1
Kể từ bây giờ (tháng 1 năm 2017), bạn sẽ liệt kê dịch vụ [providers]trong tệp mô-đun của mình chứ không phải trong bootstrap(), phải không?
Jason Swett

5
Tại sao không đặt ApiServiceAppModule's providers, và do đó tránh sự cần thiết CoreModule? (Không chắc đây là những gì @JasonSwett đang đề xuất.)
Jan Aagaard

1
@JasonGoemaat Bạn có thể thêm ví dụ về cách bạn sử dụng nó trong thành phần không? Chúng tôi có thể nhập ApiServicehàng đầu nhưng tại sao sau đó lại bận tâm đặt nó vào mảng nhà cung cấp của CoreModule và sau đó nhập cái đó trong app.module ... nó vẫn chưa nhấp cho tôi.
hogan

Vì vậy, việc đưa dịch vụ vào nhà cung cấp mô-đun sẽ cung cấp một singleton cho mô-đun đó. Và đưa dịch vụ lên các nhà cung cấp Thành phần sẽ tạo ra một phiên bản mới cho mỗi phiên bản của thành phần? Có đúng không?
BrunoLM

@BrunoLM Tôi đã tạo một ứng dụng thử nghiệm để giúp hiển thị những gì đang xảy ra. Điều thú vị là mặc dù TestServiceđược chỉ định trong cả hai mô-đun lõi và ứng dụng, nhưng các trường hợp không được tạo cho các mô-đun vì nó được cung cấp bởi thành phần sao cho góc cạnh không bao giờ làm cho cây kim phun cao lên. Vì vậy, nếu bạn cung cấp một dịch vụ trong mô-đun của mình và không bao giờ sử dụng nó, một thể hiện dường như không được tạo.
Jason Goemaat

24

Tôi biết góc cạnh có kim phun phân cấp như Thierry nói.

Nhưng tôi có một lựa chọn khác ở đây trong trường hợp bạn tìm thấy một trường hợp sử dụng mà bạn không thực sự muốn tiêm nó cho phụ huynh.

Chúng tôi có thể đạt được điều đó bằng cách tạo một phiên bản của dịch vụ và cung cấp luôn trả lại điều đó.

import { provide, Injectable } from '@angular/core';
import { Http } from '@angular/core'; //Dummy example of dependencies

@Injectable()
export class YourService {
  private static instance: YourService = null;

  // Return the instance of the service
  public static getInstance(http: Http): YourService {
    if (YourService.instance === null) {
       YourService.instance = new YourService(http);
    }
    return YourService.instance;
  }

  constructor(private http: Http) {}
}

export const YOUR_SERVICE_PROVIDER = [
  provide(YourService, {
    deps: [Http],
    useFactory: (http: Http): YourService => {
      return YourService.getInstance(http);
    }
  })
];

Và sau đó trên thành phần của bạn, bạn sử dụng phương thức cung cấp tùy chỉnh của bạn.

@Component({
  providers: [YOUR_SERVICE_PROVIDER]
})

Và bạn nên có một dịch vụ đơn lẻ mà không phụ thuộc vào người tiêm phân cấp.

Tôi không nói rằng đây là một cách tốt hơn, chỉ trong trường hợp ai đó gặp vấn đề trong đó người tiêm thuốc phân cấp không thể thực hiện được.


1
Nên SHARE_SERVICE_PROVIDERYOUR_SERVICE_PROVIDERtrong thành phần? Ngoài ra, tôi giả sử rằng việc nhập tệp dịch vụ là cần thiết như bình thường và hàm tạo sẽ vẫn có tham số loại 'YourService', phải không? Tôi thích điều này tôi nghĩ, cho phép bạn đảm bảo một singleton và không phải đảm bảo dịch vụ được cung cấp theo thứ bậc. Nó cũng cho phép các thành phần riêng lẻ có được bản sao của riêng mình bằng cách chỉ liệt kê dịch vụ providersthay vì nhà cung cấp đơn lẻ, phải không?
Jason Goemaat

@JasonGoemaat bạn nói đúng. Đã chỉnh sửa mà. Chính xác, bạn thực hiện chính xác theo cách tương tự trong hàm tạo và trên các nhà cung cấp của thành phần mà bạn thêm YOUR_SERVICE_PROVIDER. Có, tất cả các thành phần sẽ có cùng một thể hiện bằng cách chỉ cần thêm nó vào các nhà cung cấp.
Joel Almeida

Tại thời điểm một nhà phát triển sử dụng điều này, họ nên tự hỏi "tại sao tôi thậm chí còn sử dụng Angular nếu tôi sẽ không sử dụng các cơ chế mà Angular cung cấp cho tình huống này?" Cung cấp dịch vụ ở cấp ứng dụng phải đủ cho mọi tình huống trong bối cảnh của Angular.
RyNo

1
1 Mặc dù đây là một cách để tạo ra các dịch vụ singleton nó phục vụ rất độc đáo như một cách để tạo ra một multiton dịch vụ bằng cách đơn giản thay đổi instancetài sản thành một bản đồ giá trị khóa của trường
Precastic

1
@RyKhông tôi có thể tưởng tượng một ứng dụng không yêu cầu dịch vụ cho mọi tuyến đường hoặc mô-đun có thể sử dụng lại muốn có một cá thể tĩnh và muốn sử dụng cùng một thể hiện với bất kỳ mô-đun nào khác sử dụng nó. Có thể một cái gì đó tạo ra một kết nối ổ cắm web đến máy chủ và xử lý tin nhắn. Có lẽ chỉ một vài tuyến đường trong ứng dụng muốn sử dụng nó nên không cần tạo phiên bản dịch vụ và kết nối ổ cắm web khi ứng dụng khởi động nếu không cần thiết. Bạn có thể lập trình xung quanh đó để có các thành phần 'init' dịch vụ ở mọi nơi nó được sử dụng, nhưng các singletons theo yêu cầu sẽ hữu ích.
Jason Goemaat

16

Cú pháp đã được thay đổi. Kiểm tra liên kết này

Phụ thuộc là singletons trong phạm vi của một người tiêm. Trong ví dụ dưới đây, một cá thể HeroService được chia sẻ giữa các HeroesComponent và các con HeroListComponent của nó.

Bước 1. Tạo lớp singleton với trình trang trí @Injectable

@Injectable()
export class HeroService {
  getHeroes() { return HEROES;  }
}

Bước 2. Tiêm vào hàm tạo

export class HeroListComponent { 
  constructor(heroService: HeroService) {
    this.heroes = heroService.getHeroes();
  }

Bước 3. Đăng ký nhà cung cấp

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    routing,
    HttpModule,
    JsonpModule
  ],
  declarations: [
    AppComponent,
    HeroesComponent,
    routedComponents
  ],
  providers: [
    HeroService
  ],
  bootstrap: [
    AppComponent
  ]
})
export class AppModule { }

Điều gì xảy ra nếu Injectablelớp của tôi không phải là một dịch vụ và chỉ chứa các staticchuỗi để sử dụng toàn cầu?
Syed Ali Taqi

2
như nhà cung cấp này: [{cung cấp: 'API_URL', useValue: ' coolapi.com '}]
Whisher

7

Thêm trình @Injectabletrang trí vào Dịch vụ đăng ký làm nhà cung cấp trong Mô-đun gốc sẽ biến nó thành một đơn vị.


Chỉ cần cho tôi biết nếu tôi hiểu nó. Nếu tôi làm những gì bạn nói, ok, nó sẽ là một singleton. Nếu, bên cạnh đó, dịch vụ cũng là một nhà cung cấp trong một mô-đun khác, nó sẽ không còn là một đơn, phải không? Vì thứ bậc.
heringer

1
Và không đăng ký nhà cung cấp trong trang trí @Component của các trang.
Laura

@Laura. Tôi vẫn nhập nó vào các thành phần thực sự sử dụng dịch vụ?
Đánh dấu

@Mark Có, bạn cần nhập nó, và sau đó bạn chỉ cần khai báo nó constructornhư sau: import { SomeService } from '../../services/some/some'; @Component({ selector: 'page-selector', templateUrl: 'page.html', }) export class SomePage { constructor( public someService: SomeService ) { }
Laura

6

điều này dường như đang làm việc tốt cho tôi

@Injectable()
export class MyStaticService {
  static instance: MyStaticService;

  constructor() {
    return MyStaticService.instance = MyStaticService.instance || this;
  }
}

8
Tôi sẽ gọi đây là một mô hình chống Angular2. Cung cấp dịch vụ một cách chính xác và Angular2 sẽ luôn tiêm cùng một ví dụ. Xem thêm stackoverflow.com/questions/12755539/
Mạnh

3
@ Günter Zöchbauer, xin vui lòng cho một số lời khuyên liên quan đến "Cung cấp dịch vụ chính xác và Angular2 sẽ luôn tiêm cùng một ví dụ." ? Bởi vì nó không rõ ràng và tôi không thể tìm thấy bất kỳ thông tin hữu ích nào bằng cách googling.
nowiko

Tôi vừa đăng câu trả lời này có thể giúp ích cho câu hỏi của bạn stackoverflow.com/a/38781447/217408 (xem thêm liên kết ở đó)
Günter Zöchbauer

2
Đây là hoàn hảo. Bạn nên sử dụng phương pháp tiêm phụ thuộc của các ống kính, nhưng không có hại gì khi sử dụng mẫu này để chắc chắn rằng dịch vụ của bạn là một đơn vị khi bạn mong đợi. Có khả năng tiết kiệm rất nhiều thời gian săn bọ chỉ vì bạn tiêm cùng một dịch vụ ở hai nơi khác nhau.
PaulMolloy

Tôi đã sử dụng mô hình này để xác định rằng vấn đề tôi gặp phải là do dịch vụ không phải là đơn lẻ
hr-tis

5

Dưới đây là một ví dụ hoạt động với phiên bản Angular 2.3. Chỉ cần gọi hàm tạo của dịch vụ theo cách độc lập như hàm tạo này (private _userService: UserService). Và nó sẽ tạo ra một singleton cho ứng dụng.

user.service.ts

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Rx';
import { Subject }    from 'rxjs/Subject';
import { User } from '../object/user';


@Injectable()
export class UserService {
    private userChangedSource;
    public observableEvents;
    loggedUser:User;

    constructor() {
       this.userChangedSource = new Subject<any>();
       this.observableEvents = this.userChangedSource.asObservable();
    }

    userLoggedIn(user:User) {
        this.loggedUser = user;
        this.userChangedSource.next(user);
    }

    ...
}

app.component.ts

import { Component } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { UserService } from '../service/user.service';
import { User } from '../object/user';

@Component({
    selector: 'myApp',
    templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
    loggedUser:User;

    constructor(private _userService:UserService) { 
        this._userService.observableEvents.subscribe(user => {
                this.loggedUser = user;
                console.log("event triggered");
        });
    }
    ...
}

4

A singleton servicelà một dịch vụ chỉ tồn tại một thể hiện trong một ứng dụng.

(2) cách cung cấp dịch vụ đơn cho ứng dụng của bạn.

  1. sử dụng providedIntài sản, hoặc

  2. cung cấp mô-đun trực tiếp trong AppModuleứng dụng

Sử dụng được cung cấp trong

Bắt đầu với Angular 6.0, cách ưa thích để tạo dịch vụ đơn lẻ là đặt providedIngốc trên @Injectable()trang trí của dịch vụ . Điều này nói với Angular để cung cấp dịch vụ trong thư mục gốc.

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

@Injectable({
  providedIn: 'root',
})
export class UserService {
}

Mảng nhà cung cấp NgModule

Trong các ứng dụng được xây dựng với các phiên bản Angular trước 6.0, các dịch vụ được đăng ký mảng nhà cung cấp NgModule như sau:

@NgModule({
  ...
  providers: [UserService],
  ...
})

Nếu đây NgModulelà root AppModule, UserService sẽ là một singleton và có sẵn trong toàn bộ ứng dụng. Mặc dù bạn có thể thấy nó được mã hóa theo cách này, nhưng sử dụng thuộc providedIntính của trình @Injectable()trang trí trên chính dịch vụ thì tốt hơn là Angular 6.0 vì nó làm cho dịch vụ của bạn có thể bị rung.


3

Bạn có thể sử dụng useValuetrong các nhà cung cấp

import { MyService } from './my.service';

@NgModule({
...
  providers: [ { provide: MyService, useValue: new MyService() } ],
...
})

5
useValuekhông liên quan đến singleton. Usevalue chỉ để truyền một giá trị thay vì Type( useClass) mà DI gọi newhoặc useFactorynơi một hàm được truyền trả về giá trị khi được gọi bởi DI. Angular DI duy trì một trường hợp duy nhất cho mỗi nhà cung cấp tự động. Chỉ cung cấp nó một lần và bạn có một singleton. Xin lỗi, tôi phải downvote vì đó chỉ là thông tin không hợp lệ: - /
Günter Zöchbauer

3

Từ Angular @ 6, bạn có thể có providedInmột Injectable.

@Injectable({
  providedIn: 'root'
})
export class UserService {

}

Kiểm tra tài liệu ở đây

Có hai cách để biến dịch vụ thành một đơn vị trong Angular:

  1. Khai báo rằng dịch vụ nên được cung cấp trong thư mục gốc.
  2. Bao gồm dịch vụ trong AppModule hoặc trong một mô-đun chỉ được AppModule nhập.

Bắt đầu với Angular 6.0, cách ưa thích để tạo một dịch vụ đơn lẻ là chỉ định dịch vụ cần được cung cấp trong thư mục gốc. Điều này được thực hiện bằng cách cài đặt được cung cấp để root trên trang trí @Injectable của dịch vụ:


Điều này là tốt, nhưng bạn cũng có thể gặp sự cố không mong muốn với các biến không có ở đó có thể được giải quyết bằng cách khai báo một số mục public static.
cjbarth

2

Chỉ cần khai báo dịch vụ của bạn là nhà cung cấp trong app.module.ts mà thôi.

Nó đã làm công việc cho tôi.

providers: [Topic1Service,Topic2Service,...,TopicNService],

sau đó hoặc kích hoạt nó bằng tham số riêng của hàm tạo:

constructor(private topicService: TopicService) { }

hoặc vì nếu dịch vụ của bạn được sử dụng từ html, tùy chọn -prod sẽ yêu cầu:

Property 'topicService' is private and only accessible within class 'SomeComponent'.

thêm một thành viên cho dịch vụ của bạn và điền nó với thể hiện nhận được trong hàm tạo:

export class SomeComponent {
  topicService: TopicService;
  constructor(private topicService: TopicService) { 
    this.topicService= topicService;
  }
}

0
  1. Nếu bạn muốn tạo dịch vụ đơn ở cấp ứng dụng, bạn nên xác định nó trong app.module.ts

    nhà cung cấp: [MyApplicationService] (bạn cũng có thể định nghĩa tương tự trong mô-đun con để làm cho mô-đun đó cụ thể)

    • Không thêm dịch vụ này trong nhà cung cấp tạo một thể hiện cho thành phần đó phá vỡ khái niệm singleton, chỉ cần tiêm qua hàm tạo.
  2. Nếu bạn muốn xác định dịch vụ singleton ở cấp thành phần tạo dịch vụ, hãy thêm dịch vụ đó vào app.module.ts và thêm mảng nhà cung cấp bên trong thành phần cụ thể như được hiển thị bên dưới snipet.

    @Component ({selector: 'app-root', templateUrl: './test.component.html', styleUrls: ['./test.component.scss'], nhà cung cấp: [TestMyService]})

  3. Angular 6 cung cấp cách mới để thêm dịch vụ ở cấp ứng dụng. Thay vì thêm một lớp dịch vụ vào mảng nhà cung cấp [] trong AppModule, bạn có thể đặt cấu hình sau trong @Injectable ():

    @Injectable ({cung cấp: 'root'}) lớp xuất khẩu MyService {...}

"Cú pháp mới" cung cấp một lợi thế mặc dù: Dịch vụ có thể được tải một cách lười biếng bởi Angular (đằng sau hậu trường) và mã dự phòng có thể được xóa tự động. Điều này có thể dẫn đến hiệu suất và tốc độ tải tốt hơn - mặc dù điều này thực sự chỉ có tác dụng đối với các dịch vụ và ứng dụng lớn hơn nói chung.


0

Ngoài những câu trả lời xuất sắc ở trên, có thể còn thiếu một thứ gì khác nếu những thứ trong đĩa đơn của bạn vẫn không hoạt động như một đĩa đơn. Tôi gặp vấn đề khi gọi một hàm công khai trên singleton và thấy rằng nó đang sử dụng các biến sai. Nó chỉ ra rằng vấn đề thislà không được đảm bảo ràng buộc với singleton cho bất kỳ chức năng nào trong singleton. Điều này có thể được sửa chữa bằng cách làm theo lời khuyên ở đây , như vậy:

@Injectable({
  providedIn: 'root',
})
export class SubscriptableService {
  public serviceRequested: Subject<ServiceArgs>;
  public onServiceRequested$: Observable<ServiceArgs>;

  constructor() {
    this.serviceRequested = new Subject<ServiceArgs>();
    this.onServiceRequested$ = this.serviceRequested.asObservable();

    // save context so the singleton pattern is respected
    this.requestService = this.requestService.bind(this);
  }

  public requestService(arg: ServiceArgs) {
    this.serviceRequested.next(arg);
  }
}

Ngoài ra, bạn có thể chỉ cần khai báo các thành viên lớp public staticthay vì public, bối cảnh sẽ không thành vấn đề, nhưng bạn sẽ phải truy cập chúng như SubscriptableService.onServiceRequested$thay vì sử dụng nội xạ phụ thuộc và truy cập chúng qua this.subscriptableService.onServiceRequested$.


0

Dịch vụ phụ huynh và trẻ em

Tôi đã gặp rắc rối với một dịch vụ cha mẹ và con của nó sử dụng các trường hợp khác nhau. Để buộc một trường hợp được sử dụng, bạn có thể đặt bí danh cho phụ huynh có tham chiếu đến đứa trẻ trong các nhà cung cấp mô-đun ứng dụng của bạn. Phụ huynh sẽ không thể truy cập các thuộc tính của trẻ, nhưng cùng một thể hiện sẽ được sử dụng cho cả hai dịch vụ. https://angular.io/guide/dependency-injection-providers#aliased- class -providers

app.module.ts

providers: [
  ChildService,
  // Alias ParentService w/ reference to ChildService
  { provide: ParentService, useExisting: ChildService}
]

Các dịch vụ được sử dụng bởi các thành phần bên ngoài phạm vi mô-đun ứng dụng của bạn

Khi tạo một thư viện bao gồm một thành phần và một dịch vụ, tôi gặp phải một vấn đề trong đó hai trường hợp sẽ được tạo. Một bởi dự án Angular của tôi và một bởi thành phần bên trong thư viện của tôi. Cách khắc phục:

my-bên ngoài.component.ts

@Component({...})
export class MyOutsideComponent {
  @Input() serviceInstance: MyOutsideService;
  ...
}

my-Inside.component.ts

  constructor(public myService: MyOutsideService) { }

my-Inside.component.hmtl

<app-my-outside [serviceInstance]="myService"></app-my-outside>

Ý của bạn là trả lời câu hỏi của bạn? Nếu vậy, bạn có thể tách câu trả lời thành Câu trả lời chính thức trên StackOverflow, bằng cách cắt / dán nó vào trường Trả lời sau khi Câu hỏi được đăng.
ryanwebjackson
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.