Was ist der Zweck der Bereitstellung des Injectable-Dekorators beim Generieren von Diensten in Angular 6?

136

Beim Generieren von Diensten in der Angular-CLI werden zusätzliche Metadaten mit der Eigenschaft "bereitgestellt in" mit dem Standardwert "root" für den Injectable-Dekorator hinzugefügt.

@Injectable({
  providedIn: 'root',
})

Was genau macht vorausgesetzt? Ich gehe davon aus, dass dies den Dienst wie einen Singleton-Dienst vom Typ 'global' für die gesamte Anwendung verfügbar macht. Wäre es jedoch nicht sauberer, solche Dienste im Provider-Array des AppModule zu deklarieren?

AKTUALISIEREN:

Für alle anderen bietet der folgende Absatz eine weitere gute Erklärung, insbesondere wenn Sie Ihren Dienst nur für ein Funktionsmodul bereitstellen möchten.

Es gibt jetzt eine neue, empfohlene Möglichkeit, einen Anbieter direkt im @Injectable()Dekorateur mithilfe des neuen providedIn Attributs zu registrieren . Es akzeptiert 'root'als Wert oder als Modul Ihrer Anwendung. Wenn Sie verwenden 'root', wird Ihr injectableBenutzer als Singleton in der Anwendung registriert, und Sie müssen ihn nicht zu den Anbietern des Root-Moduls hinzufügen. Wenn Sie das Modul verwenden providedIn: UsersModule, injectablewird es ebenfalls als Anbieter des Moduls registriert, UsersModuleohne es providersdem Modul hinzuzufügen . "- https://blog.ninja-squad.com/2018/05/04/what-is-new-angular -6 /

UPDATE 2:

Nach weiteren Untersuchungen habe ich entschieden, dass es nur nützlich ist, zu haben providedIn: 'root'

Wenn Sie provideeinen Dienst in einem anderen Modul als dem Root-Modul ausführen möchten , ist es besser, das providersArray in den Dekoratoren des Feature-Moduls zu verwenden, da Sie sonst von zirkulären Abhängigkeiten geplagt werden. Interessante Diskussionen finden Sie hier - https://github.com/angular/angular-cli/issues/10170

Stefan Zvonar
quelle
17
Ich denke, Ihre Updates sollten eine Antwort sein (Sie können Ihre eigenen Fragen beantworten), anstatt sie Ihrer Frage hinzuzufügen.
PhoneixS
Der wichtigste Teil ist SINGLETON, niemand erwähnt es!
Kyle Burkett

Antworten:

54

Wenn Sie BereitgestelltesIn verwenden, wird das Injizierbare als Anbieter des Moduls registriert, ohne es den Anbietern des Moduls hinzuzufügen.

Von Docs

Der Service selbst ist eine Klasse, die von der CLI generiert und mit @Injectable dekoriert wurde. Standardmäßig ist dieser Dekorator mit einer Bereitstellung -In-Eigenschaft konfiguriert, die einen Anbieter für den Dienst erstellt. In diesem Fall gibt bereitgestellt: 'root' an, dass der Dienst im Root-Injektor bereitgestellt werden soll.

Sajeetharan
quelle
4
Danke Sajeetharan. Okay, es klingt also so, als wäre es eine neue Abkürzung, um anzugeben, wo der Dienst bereitgestellt werden soll. Ich denke, meine anfängliche Präferenz wäre gewesen, in der Anbieterliste eines Moduls alle Dienste anzuzeigen, die als Anbieter deklariert sind, anstatt die verstreute Codebasis für ProvidedIn-Tags zu durchsuchen .... (?)
Stefan Zvonar
2
Gab es einen Grund für Angular, dies hinzuzufügen? Gibt es ein Problem, das dadurch gelöst wird? Ich sehe keinen Grund dafür.
Prolink007
3
Hält die AppModule / CoreModule-Definition etwas kleiner;)
Stefan Zvonar
22
@ prolink007. Durch die Verwendung von BereitgestelltemIn können die Dienste von der App verzögert geladen werden. Um dies zu testen, fügen Sie Konsolenprotokolle in Ihre Dienste ein. Auf meiner Homepage wurden 16 Dienste geladen, jetzt werden 9 geladen. Es ist schwierig, die Leistung zu quantifizieren, aber ich fühle mich besser, wenn ich weiß, dass ich Dienste erst lade, wenn sie benötigt werden :).
Stevethemacguy
3
Sie können Ihre Services baumschüttelnd machen, indem Sie mithilfe des providedInAttributs definieren, wo der Service bei Verwendung des @Injectable()Dekorators initialisiert werden soll . Anschließend sollten Sie es aus dem Anbieterattribut Ihrer NgModuleDeklaration sowie aus der Importanweisung entfernen. Dies kann dazu beitragen, die Bundle-Größe zu verringern, indem nicht verwendeter Code aus dem Bundle entfernt wird.
Flugzeuge
48

providedIn: 'root' ist der einfachste und effizienteste Weg, um Dienste bereitzustellen, seit Angular 6:

  1. Der Dienst wird anwendungsweit als Singleton verfügbar sein, ohne dass er dem Provider-Array eines Moduls hinzugefügt werden muss (z. B. Angular <= 5).
  2. Wenn der Dienst nur in einem verzögert geladenen Modul verwendet wird, wird er mit diesem Modul verzögert geladen
  3. Wenn es nie verwendet wird, ist es nicht im Build enthalten (Baum geschüttelt).

Weitere Informationen finden Sie in der Dokumentation und in den häufig gestellten Fragen zu NgModule

Übrigens:

  1. Wenn Sie keinen anwendungsweiten Singleton möchten, verwenden Sie stattdessen das Array einer Komponente des Anbieters.
  2. Wenn Sie den Umfang einschränken möchten, damit kein anderer Entwickler Ihren Dienst jemals außerhalb eines bestimmten Moduls verwendet, verwenden providersSie stattdessen das Array von NgModule.
Mick
quelle
37

Aus Dokumenten

Was ist ein injizierbarer Dekorateur?

Markiert eine Klasse als für Injector zur Erstellung verfügbar.

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

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

Der Dienst selbst ist eine Klasse, die von der CLI generiert wurde und die mit @Injectable () dekoriert ist.

Was genau macht vorausgesetzt?

Legt fest, welche Injektoren das Injektionsmittel bereitstellen, indem sie es entweder einem @ NgModule oder einem anderen InjectorType zuordnen oder angeben, dass dieses Injektionsmittel im 'Root'-Injektor bereitgestellt werden soll, der in den meisten Apps der Injektor auf Anwendungsebene ist.

providedIn: Type<any> | 'root' | null

vorausgesetztIn: 'root'

Wenn Sie den Dienst auf Stammebene bereitstellen, erstellt Angular eine einzelne gemeinsam genutzte Dienstinstanz und fügt sie in jede Klasse ein, die danach fragt. Durch die Registrierung des Anbieters in den Metadaten von @Injectable () kann Angular auch eine App optimieren, indem der Dienst aus der kompilierten App entfernt wird, wenn er nicht verwendet wird.

vorausgesetztIn: Modul

Es kann auch angegeben werden, dass ein Dienst in einem bestimmten @ NgModule bereitgestellt werden soll. Wenn Sie beispielsweise nicht möchten, dass ein Dienst für Anwendungen verfügbar ist, es sei denn, sie importieren ein von Ihnen erstelltes Modul, können Sie festlegen, dass der Dienst im Modul bereitgestellt werden soll

import { Injectable } from '@angular/core';
import { UserModule } from './user.module';

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

Diese Methode wird bevorzugt, weil sie das Schütteln von Bäumen ermöglicht ( Schütteln von Bäumen) ist ein Schritt in einem Erstellungsprozess, bei dem nicht verwendeter Code aus einer Codebasis entfernt wird ) des Dienstes aktiviert, wenn nichts injiziert wird.

Wenn im Dienst nicht angegeben werden kann, welches Modul es bereitstellen soll, können Sie auch einen Anbieter für den Dienst innerhalb des Moduls deklarieren:

import { NgModule } from '@angular/core';
import { UserService } from './user.service';

@NgModule({
  providers: [UserService],
})
export class UserModule {
}
Nipuna
quelle
4
Die beste Erklärung.
Nein,
2
Diese Antwort ist besser als die Definition in Angular Doc. sehr deutlich.
Shameera Anuranga
2
Sehr gut erklärt, vielen Dank!
Zaki Mohammed
Was ist, wenn es leer ist, wie zum Beispiel @Injectable()?
Ben Taliadoros
13

vorausgesetzt, teilt Angular mit, dass der Root-Injektor für die Erstellung einer Instanz Ihres Dienstes verantwortlich ist. Auf diese Weise bereitgestellte Dienste werden automatisch für die gesamte Anwendung verfügbar gemacht und müssen in keinem Modul aufgeführt werden.

Serviceklassen können als eigene Anbieter fungieren, weshalb die Definition im @ Injectable Decorator nur die Registrierung erfordert, die Sie benötigen.

Jawad Farooqi
quelle
4

Nach dem Documentation:

Durch die Registrierung des Anbieters in den Metadaten von @Injectable () kann Angular auch eine App optimieren, indem der Dienst aus der kompilierten App entfernt wird, wenn er nicht verwendet wird.

Maarti
quelle