Wie erstelle ich einen Singleton-Dienst in Angular 2?

141

Ich habe gelesen, dass beim Injizieren beim Bootstrapping alle untergeordneten Elemente dieselbe Instanz verwenden sollten, aber meine Haupt- und Header-Komponenten (Haupt-App enthält Header-Komponente und Router-Outlet) erhalten jeweils eine separate Instanz meiner Dienste.

Ich habe einen FacebookService, mit dem ich die Facebook-Javascript-API anrufe, und einen UserService, der den FacebookService verwendet. Hier ist mein Bootstrap:

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

Aus meiner Protokollierung geht hervor, dass der Bootstrap-Aufruf beendet ist. Dann wird der FacebookService und dann der UserService erstellt, bevor der Code in jedem der Konstruktoren ausgeführt wird, die MainAppComponent, die HeaderComponent und die DefaultComponent:

Geben Sie hier die Bildbeschreibung ein

Jason Goemaat
quelle
8
Sie sind sicher , dass Sie nicht hinzugefügt UserServiceund FacebookServicezu providersanderswo?
Günter Zöchbauer

Antworten:

132

Jason hat vollkommen recht! Dies wird durch die Funktionsweise der Abhängigkeitsinjektion verursacht. Es basiert auf hierarchischen Injektoren.

In einer Angular2-Anwendung gibt es mehrere Injektoren:

  • Der Root, den Sie beim Bootstrapping Ihrer Anwendung konfigurieren
  • Ein Injektor pro Komponente. Wenn Sie eine Komponente in einer anderen verwenden. Der Komponenteninjektor ist ein untergeordnetes Element der übergeordneten Komponente. Die Anwendungskomponente (die Sie beim Boostrapping Ihrer Anwendung angeben) hat den Root-Injektor als übergeordneten.

Wenn Angular2 versucht, etwas in den Komponentenkonstruktor einzufügen:

  • Es untersucht den der Komponente zugeordneten Injektor. Wenn es eine übereinstimmende gibt, wird sie verwendet, um die entsprechende Instanz abzurufen. Diese Instanz wird träge erstellt und ist ein Singleton für diesen Injektor.
  • Wenn es auf dieser Ebene keinen Anbieter gibt, wird der übergeordnete Injektor (usw.) überprüft.

Wenn Sie also einen Singleton für die gesamte Anwendung haben möchten, muss der Anbieter entweder auf der Ebene des Root-Injektors oder des Injektors der Anwendungskomponente definiert sein.

Aber Angular2 wird den Injektorbaum von unten betrachten. Dies bedeutet, dass der Anbieter auf der untersten Ebene verwendet wird und der Bereich der zugeordneten Instanz diese Ebene ist.

Siehe diese Frage für weitere Details:

Thierry Templier
quelle
1
Danke, das erklärt es gut. Es war für mich nur kontraintuitiv, weil dies irgendwie mit dem in sich geschlossenen Komponentenparadigma von Winkel 2 bricht. Nehmen wir also an, ich erstelle eine Bibliothek mit Komponenten für Facebook, aber ich möchte, dass alle einen Singleton-Dienst verwenden. Möglicherweise gibt es eine Komponente, um das Profilbild des angemeldeten Benutzers anzuzeigen, und eine andere, die veröffentlicht werden kann. Die App, die diese Komponenten verwendet, muss den Facebook-Dienst als Anbieter einbeziehen, auch wenn sie den Dienst selbst nicht nutzt. Ich könnte einfach einen Dienst mit einer 'getInstance ()' - Methode zurückgeben, die den Singleton des realen Dienstes verwaltet ...
Jason Goemaat
@tThierryTemplier Wie würde ich das Gegenteil tun? Ich habe eine gemeinsame Serviceklasse, die ich in mehrere Komponenten einfügen möchte, aber jedes Mal eine neue Instanz instanziiere (Anbieter- / Direktivenoptionen sollten in der nächsten Version veraltet und entfernt werden)
Boban Stojanovski
Es tut mir leid, dass ich so dumm bin, aber mir ist nicht klar, wie Sie einen Singleton-Service erstellen. Können Sie das genauer erklären?
Gyozo Kudor
Um mit einer einzelnen Instanz eines Dienstes zu arbeiten, sollte dieser in app.module.ts oder in app.component.ts als Anbieter deklariert werden?
user1767316
Die Deklaration jedes Dienstes nur in app.module.ts hat den Job für mich erledigt.
user1767316
142

Update (Winkel 6 +)

Die empfohlene Methode zum Erstellen eines Singleton-Dienstes wurde geändert. Es wird jetzt empfohlen, im @InjectableDekorator des Dienstes anzugeben, dass er im 'root' bereitgestellt werden soll. Dies ist für mich sehr sinnvoll und es besteht keine Notwendigkeit mehr, alle bereitgestellten Dienste in Ihren Modulen aufzulisten. Sie importieren die Dienste nur dann, wenn Sie sie benötigen, und sie registrieren sich an der richtigen Stelle. Sie können auch ein Modul angeben, damit es nur bereitgestellt wird, wenn das Modul importiert wird.

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

Update (Winkel 2)

Mit NgModule besteht die Möglichkeit, dies jetzt zu tun, darin, ein 'CoreModule' mit Ihrer Serviceklasse darin zu erstellen und den Service bei den Anbietern des Moduls aufzulisten. Anschließend importieren Sie das Kernmodul in Ihr Haupt-App-Modul, das allen Kindern, die diese Klasse in ihren Konstruktoren anfordern, die eine Instanz bereitstellt:

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 { }

Ursprüngliche Antwort

Wenn Sie einen Anbieter in auflisten bootstrap(), müssen Sie ihn nicht in Ihrem Komponentendekorator auflisten:

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) {}
}

Wenn Sie Ihre Klasse in "Provider" auflisten, wird eine neue Instanz davon erstellt. Wenn eine übergeordnete Komponente sie bereits auflistet, müssen die untergeordneten Komponenten dies nicht tun. In diesem Fall erhalten sie eine neue Instanz.

Jason Goemaat
quelle
1
Ab sofort (Januar 2017) würden Sie den Dienst [providers]in Ihrer Moduldatei auflisten, nicht in bootstrap(), oder?
Jason Swett
5
Warum nicht setzen ApiServicein AppModule‚s providersund damit die Notwendigkeit vermeiden CoreModule? (Ich bin mir nicht sicher, ob @JasonSwett dies vorschlägt.)
Jan Aagaard
1
@JasonGoemaat Können Sie das Beispiel hinzufügen, wie Sie es in der Komponente verwenden? Wir könnten ApiServicedas oben importieren, aber warum sollten wir uns dann überhaupt die Mühe machen, es in das Provider-Array des CoreModule zu stellen und dieses dann in app.module zu importieren ... es hat für mich noch nicht geklickt.
Hogan
Wenn Sie den Dienst auf den Modulanbieter stellen, wird ein Singleton für dieses Modul bereitgestellt. Wenn Sie den Dienst auf die Komponentenanbieter stellen, wird für jede Instanz der Komponente eine neue Instanz erstellt. Ist das richtig?
BrunoLM
@BrunoLM Ich habe eine Test-App erstellt , um zu zeigen, was passiert. Interessant ist, dass TestServiceInstanzen für die Module nicht erstellt werden , obwohl sie sowohl in den Kern- als auch in den App-Modulen angegeben sind, da sie von der Komponente bereitgestellt werden, sodass der Winkel im Injektorbaum nie so hoch ist. Wenn Sie also einen Dienst in Ihrem Modul bereitstellen und ihn niemals verwenden, scheint keine Instanz erstellt zu werden.
Jason Goemaat
24

Ich weiß, dass Angular hierarchische Injektoren hat, wie Thierry sagte.

Aber ich habe hier eine andere Option, falls Sie einen Anwendungsfall finden, bei dem Sie ihn dem Elternteil nicht wirklich injizieren möchten.

Wir können dies erreichen, indem wir eine Instanz des Dienstes erstellen und diese bei Bereitstellung immer zurückgeben.

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);
    }
  })
];

Und dann verwenden Sie für Ihre Komponente Ihre benutzerdefinierte Bereitstellungsmethode.

@Component({
  providers: [YOUR_SERVICE_PROVIDER]
})

Und Sie sollten einen Singleton-Service haben, ohne von den hierarchischen Injektoren abhängig zu sein.

Ich sage nicht, dass dies ein besserer Weg ist, nur für den Fall, dass jemand ein Problem hat, bei dem hierarchische Injektoren nicht möglich sind.

Joel Almeida
quelle
1
Sollte das SHARE_SERVICE_PROVIDERsein YOUR_SERVICE_PROVIDERin der Komponente? Außerdem gehe ich davon aus, dass der Import der Servicedatei wie gewohnt erforderlich ist und der Konstruktor weiterhin einen Parameter vom Typ 'YourService' hat, oder? Ich denke, das gefällt mir, ermöglicht es Ihnen, einen Singleton zu garantieren und muss nicht sicherstellen, dass der Dienst in der Hierarchie bereitgestellt wird. Es ermöglicht auch einzelnen Komponenten, ihre eigene Kopie zu erhalten, indem nur der Dienst providersanstelle des Singleton-Anbieters aufgelistet wird, oder?
Jason Goemaat
@ JasonGoemaat du hast recht. Das bearbeitet. Genau so machen Sie es im Konstruktor und bei den Anbietern dieser Komponente, die Sie hinzufügen YOUR_SERVICE_PROVIDER. Ja, alle Komponenten erhalten dieselbe Instanz, indem sie nur den Anbietern hinzugefügt werden.
Joel Almeida
An dem Punkt, an dem ein Entwickler dies verwendet, sollte er sich fragen: "Warum verwende ich Angular überhaupt, wenn ich die Mechanismen, die Angular für diese Situation bereitstellt, nicht verwenden werde?" Die Bereitstellung des Dienstes auf Anwendungsebene sollte für jede Situation im Kontext von Angular ausreichend sein.
RyNo
1
+1 Obwohl dies eine Möglichkeit ist, Singleton-Dienste zu erstellen, dient es sehr gut dazu, einen Multiton- Dienst zu erstellen, indem die instanceEigenschaft einfach in eine Schlüsselwertzuordnung von Instanzen
geändert wird
1
@ RyNo Ich kann mir eine App vorstellen, die nicht für jede Route einen Dienst benötigt, oder ein wiederverwendbares Modul, das eine statische Instanz möchte und dieselbe Instanz mit allen anderen Modulen verwenden möchte, die sie verwenden. Möglicherweise etwas, das eine Web-Socket-Verbindung zum Server herstellt und Nachrichten verarbeitet. Möglicherweise möchten nur wenige Routen in der App sie verwenden, sodass beim Starten der App keine Dienstinstanz und keine Web-Socket-Verbindung erstellt werden muss, wenn sie nicht benötigt wird. Sie können dies so programmieren, dass die Komponenten den Dienst überall dort "initiieren", wo er verwendet wird. Bei Bedarf wären jedoch Singletons hilfreich.
Jason Goemaat
16

Die Syntax wurde geändert. Überprüfen Sie diesen Link

Abhängigkeiten sind Singletons im Rahmen eines Injektors. Im folgenden Beispiel wird eine einzelne HeroService-Instanz von der HeroesComponent und ihren untergeordneten HeroListComponent-Instanzen gemeinsam genutzt.

Schritt 1. Erstellen Sie eine Singleton-Klasse mit @Injectable Decorator

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

Schritt 2. In den Konstruktor injizieren

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

Schritt 3. Anbieter registrieren

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    routing,
    HttpModule,
    JsonpModule
  ],
  declarations: [
    AppComponent,
    HeroesComponent,
    routedComponents
  ],
  providers: [
    HeroService
  ],
  bootstrap: [
    AppComponent
  ]
})
export class AppModule { }
Manish Jain
quelle
Was ist, wenn meine InjectableKlasse kein Dienst ist und nur staticZeichenfolgen für den globalen Gebrauch enthält?
Syed Ali Taqi
2
wie diese Anbieter: [{bereitstellen: 'API_URL', useValue: ' coolapi.com '}]
Whisher
10

A singleton serviceist ein Dienst, für den in einer App nur eine Instanz vorhanden ist.

Es gibt (2) Möglichkeiten , einen Singleton-Dienst für Ihre Anwendung bereitzustellen.

  1. Verwenden Sie die providedInEigenschaft, oder

  2. Stellen Sie das Modul direkt in AppModuleder Anwendung bereit

Mit zur Verfügung gestelltIn

Ab Angular 6.0 besteht die bevorzugte Methode zum Erstellen eines Singleton-Dienstes darin, providedInim @Injectable()Decorator des Dienstes als Root festzulegen. Dadurch wird Angular angewiesen, den Dienst im Anwendungsstamm bereitzustellen.

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

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

Array von NgModule-Anbietern

In Apps, die mit Angular-Versionen vor 6.0 erstellt wurden, werden Dienste wie folgt als NgModule-Anbieter-Arrays registriert:

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

Wenn dies NgModuleder Stamm wäre AppModule, wäre der UserService ein Singleton und in der gesamten App verfügbar. Obwohl Sie möglicherweise sehen, dass es auf diese Weise codiert ist, ist die Verwendung der providedInEigenschaft des @Injectable()Dekorateurs für den Dienst selbst ab Angular 6.0 vorzuziehen, da dies Ihre Dienste baumschüttelnd macht.

AbolfazlR
quelle
7

Wenn Sie @Injectabledem Service einen Dekorator hinzufügen und ihn als Anbieter im Root-Modul registrieren, wird er zu einem Singleton.

Bresleveloper
quelle
Sag mir einfach, ob ich es verstehe. Wenn ich tue, was du gesagt hast, ok, wird es ein Singleton sein. Wenn der Dienst außerdem ein Anbieter in einem anderen Modul ist, ist er kein Singleton mehr, oder? Wegen der Hierarchie.
Heringer
1
Und registrieren Sie den Anbieter nicht im @Component Decorator der Seiten.
Laura
@Laura. Importiere ich es trotzdem in Komponenten, die den Service tatsächlich nutzen?
Mark
@ Mark Ja, Sie müssen es importieren, und dann müssen Sie es nur so deklarieren constructor: import { SomeService } from '../../services/some/some'; @Component({ selector: 'page-selector', templateUrl: 'page.html', }) export class SomePage { constructor( public someService: SomeService ) { }
Laura
6

Das scheint gut für mich zu funktionieren

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

  constructor() {
    return MyStaticService.instance = MyStaticService.instance || this;
  }
}
Captain Harlock
quelle
8
Ich würde dies ein Angular2-Anti-Pattern nennen. Stellen Sie den Dienst korrekt bereit und Angular2 injiziert immer dieselbe Instanz. Siehe auch stackoverflow.com/questions/12755539/…
Günter Zöchbauer
3
@ Günter Zöchbauer, bitte geben Sie einen Hinweis zu "Stellen Sie den Service korrekt bereit und Angular2 injiziert immer die gleiche Instanz." ? Weil es unklar ist und ich durch googeln keine nützlichen Informationen finden konnte.
Nowiko
Ich habe gerade diese Antwort gepostet, die bei Ihrer Frage helfen könnte stackoverflow.com/a/38781447/217408 (siehe auch den Link dort)
Günter Zöchbauer
2
Dies ist perfekt. Sie sollten Angulars eigene Abhängigkeitsinjektion verwenden, aber es schadet nicht, dieses Muster zu verwenden, um absolut sicher zu sein, dass Ihr Dienst ein Singleton ist, wenn Sie dies erwarten. Spart möglicherweise viel Zeit bei der Suche nach Fehlern, nur weil Sie denselben Service an zwei verschiedenen Orten injizieren.
PaulMolloy
Ich habe dieses Muster verwendet, um festzustellen, dass das Problem, mit dem ich konfrontiert war, darin bestand, dass der Dienst nicht singleton war
hr-tis
5

Hier ist ein Arbeitsbeispiel mit Angular Version 2.3. Rufen Sie einfach den Konstruktor des Dienstes wie diesen Konstruktor auf (private _userService: UserService). Und es wird ein Singleton für die App erstellt.

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");
        });
    }
    ...
}
David Dehghan
quelle
3

Sie können useValuein Anbietern verwenden

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

@NgModule({
...
  providers: [ { provide: MyService, useValue: new MyService() } ],
...
})
Roman Rhrn Nesterov
quelle
5
useValueist nicht mit Singleton verwandt. Usevalue dient nur dazu, einen Wert anstelle von a Type( useClass) zu übergeben, das DI aufruft, newoder useFactorywenn eine Funktion übergeben wird, die den Wert zurückgibt, wenn sie von DI aufgerufen wird. Angular DI verwaltet automatisch eine einzelne Instanz pro Anbieter. Geben Sie es nur einmal an und Sie haben einen Singleton. Entschuldigung, ich muss abstimmen, weil es nur ungültige Informationen sind: - /
Günter Zöchbauer
3

Von Angular @ 6 können Sie providedInin einem Injectable.

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

}

Überprüfen Sie die Dokumente hier

Es gibt zwei Möglichkeiten, einen Dienst in Angular zu einem Singleton zu machen:

  1. Deklarieren Sie, dass der Dienst im Anwendungsstamm bereitgestellt werden soll.
  2. Fügen Sie den Dienst in das AppModule oder in ein Modul ein, das nur vom AppModule importiert wird.

Ab Angular 6.0 besteht die bevorzugte Methode zum Erstellen von Singleton-Diensten darin, auf dem Dienst anzugeben, dass er im Anwendungsstamm bereitgestellt werden soll. Dies erfolgt durch Setzen von Bereitgestelltem auf root im @Injectable-Dekorator des Dienstes:

Sabithpocker
quelle
Dies ist gut, aber es kann auch zu unerwarteten Problemen mit nicht vorhandenen Variablen kommen, die möglicherweise durch Deklarieren einiger Elemente behoben werden public static.
CJBarth
2

Deklarieren Sie Ihren Dienst einfach nur in app.module.ts als Anbieter.

Es hat den Job für mich gemacht.

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

dann instanziieren Sie es entweder mit einem privaten Konstruktorparameter:

constructor(private topicService: TopicService) { }

oder da, wenn Ihr Dienst von HTML verwendet wird, die Option -prod Folgendes beansprucht:

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

Fügen Sie ein Mitglied für Ihren Dienst hinzu und füllen Sie es mit der im Konstruktor empfangenen Instanz:

export class SomeComponent {
  topicService: TopicService;
  constructor(private topicService: TopicService) { 
    this.topicService= topicService;
  }
}
user1767316
quelle
0
  1. Wenn Sie Service Singleton auf Anwendungsebene erstellen möchten, sollten Sie es in app.module.ts definieren

    Anbieter: [MyApplicationService] (Sie können dasselbe auch im untergeordneten Modul definieren, um es modulspezifisch zu machen.)

    • Fügen Sie diesen Dienst nicht in den Provider ein, der eine Instanz für diese Komponente erstellt, die das Singleton-Konzept verletzt. Fügen Sie ihn einfach über den Konstruktor ein.
  2. Wenn Sie einen Singleton-Service auf Komponentenebene definieren möchten, fügen Sie diesen Service in app.module.ts hinzu und fügen Sie das Provider-Array innerhalb einer bestimmten Komponente hinzu, wie im folgenden Snipet gezeigt.

    @Component ({Selektor: 'app-root', templateUrl: './test.component.html', styleUrls: ['./test.component.scss'], Anbieter: [TestMyService]})

  3. Angular 6 bietet eine neue Möglichkeit, Dienste auf Anwendungsebene hinzuzufügen. Anstatt dem Array "provider []" in AppModule eine Serviceklasse hinzuzufügen, können Sie in @Injectable () die folgende Konfiguration festlegen:

    @Injectable ({vorausgesetztIn: 'root'}) Exportklasse MyService {...}

Die "neue Syntax" bietet jedoch einen Vorteil: Dienste können von Angular (hinter den Kulissen) träge geladen und redundanter Code automatisch entfernt werden. Dies kann zu einer besseren Leistung und Ladegeschwindigkeit führen - obwohl dies nur für größere Dienste und Apps im Allgemeinen gilt.

Vijay Barot
quelle
0

Zusätzlich zu den oben genannten hervorragenden Antworten fehlt möglicherweise noch etwas anderes, wenn sich die Dinge in Ihrem Singleton immer noch nicht als Singleton verhalten. Ich bin auf das Problem gestoßen, als ich eine öffentliche Funktion für den Singleton aufgerufen habe und festgestellt habe, dass die falschen Variablen verwendet wurden. Es stellt sich heraus, dass das Problem darin bestand, dass thisnicht garantiert wird, dass es für öffentliche Funktionen im Singleton an den Singleton gebunden ist. Dies kann durch Anschluss an die Beratung korrigiert wird hier , wie so:

@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);
  }
}

Alternativ können Sie die Klassenmitglieder einfach als public staticstatt deklarieren public, dann spielt der Kontext keine Rolle, aber Sie müssen auf sie zugreifen, SubscriptableService.onServiceRequested$anstatt die Abhängigkeitsinjektion zu verwenden und über auf sie zuzugreifen this.subscriptableService.onServiceRequested$.

cjbarth
quelle
0

Eltern- und Kinderbetreuung

Ich hatte Probleme mit einem Elterndienst und seinem Kind, die verschiedene Instanzen verwendeten. Um die Verwendung einer Instanz zu erzwingen, können Sie das übergeordnete Element in Bezug auf das untergeordnete Element in Ihren App-Modulanbietern aliasisieren. Der Elternteil kann nicht auf die Eigenschaften des Kindes zugreifen, aber für beide Dienste wird dieselbe Instanz verwendet. 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}
]

Dienste, die von Komponenten außerhalb des Anwendungsbereichs Ihrer App-Module verwendet werden

Beim Erstellen einer Bibliothek, die aus einer Komponente und einem Dienst besteht, ist ein Problem aufgetreten, bei dem zwei Instanzen erstellt wurden. Eine von meinem Angular-Projekt und eine von der Komponente in meiner Bibliothek. Die Reparatur:

my -side.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>
Scott VandenToorn
quelle
Wollten Sie Ihre eigene Frage beantworten? In diesem Fall können Sie die Antwort in eine formelle Antwort auf StackOverflow aufteilen, indem Sie sie nach dem Posten der Frage ausschneiden / in das Feld Antwort einfügen.
Ryanwebjackson