Jaki jest cel dostarczenia z dekoratorem iniekcyjnym podczas generowania usług w Angular 6?

151

Podczas generowania usług w Angular CLI, dodaje dodatkowe metadane z właściwością „dostarczone w” z domyślną wartością „root” dla dekoratora Injectable.

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

Co dokładnie zapewnia? Zakładam, że oznacza to udostępnienie usługi jako pojedynczej usługi typu „globalnego” dla całej aplikacji, jednak czy deklarowanie takich usług w tablicy dostawców AppModule nie byłoby czystsze?

AKTUALIZACJA:

Dla wszystkich innych, poniższy akapit również zawiera inne dobre wyjaśnienie, w szczególności, jeśli chcesz świadczyć usługi tylko dla modułu funkcji.

Jest teraz nowy, zalecany sposób rejestracji dostawcy bezpośrednio w @Injectable()dekoratorze przy użyciu nowego providedIn atrybutu. Akceptuje 'root'jako wartość lub dowolny moduł aplikacji. Kiedy używasz 'root', Twój injectablebędzie zarejestrowany jako singleton w aplikacji i nie musisz go dodawać do dostawców modułu głównego. Podobnie, jeśli używasz providedIn: UsersModule, injectablejest zarejestrowany jako dostawca UsersModulebez dodawania go do providersmodułu. ”- https://blog.ninja-squad.com/2018/05/04/what-is-new-angular -6 /

AKTUALIZACJA 2:

Po dalszych badaniach zdecydowałem, że warto mieć providedIn: 'root'

Jeśli chcesz skorzystać z provideusługi w jakimkolwiek module innym niż moduł główny, lepiej użyj providerstablicy w dekoratorach modułu funkcji, w przeciwnym razie będziesz nękany cyklicznymi zależnościami. Ciekawe dyskusje do przeprowadzenia tutaj - https://github.com/angular/angular-cli/issues/10170

Stefan Zvonar
źródło
17
Myślę, że Twoje aktualizacje powinny być odpowiedzią (możesz odpowiedzieć na własne pytania) zamiast dodawać je do swojego pytania.
PhoneixS
Najważniejsza część to SINGLETON, nikt o tym nie wspomina!
Kyle Burkett

Odpowiedzi:

61

w przypadku korzystania z providedIn, element iniekcyjny jest rejestrowany jako dostawca modułu bez dodawania go do dostawców modułu.

Z Docs

Sama usługa jest klasą wygenerowaną przez CLI i ozdobioną znakiem @Injectable. Domyślnie ten dekorator jest skonfigurowany z właściwością providedIn, która tworzy dostawcę dla usługi. W tym przypadku atrybut providedIn: „root” określa, że ​​usługa powinna być świadczona w iniektorze root.

Sajeetharan
źródło
4
Dzięki Sajeetharan. Okay, więc wygląda na to, że jest to nowy skrót do określania, gdzie usługa powinna być świadczona. Chyba mój początkowy preferencji byłby patrząc na liście providerów modułu aby zobaczyć wszystkie usługi, które są zadeklarowane jako dostawców, niż uważne rozproszone bazy kodu dla tagów ProvidedIn .... (?)
Stefan Zvonar
2
Czy był jakiś powód, dla którego Angular to dodał? Czy jest jakiś problem, który to rozwiązuje? Nie widzę powodu do tego.
prolink007
3
Utrzymuje nieco mniejszą definicję AppModule / CoreModule;)
Stefan Zvonar
23
@ prolink007. Korzystanie z providedIn umożliwia leniwe ładowanie usług przez aplikację. Aby to przetestować, umieść dzienniki konsoli w swoich usługach. Moja strona domowa ładowała 16 usług, teraz ładuje się 9. Trudno oszacować wydajność, ale czuję się lepiej wiedząc, że nie ładuję usług, dopóki nie będą potrzebne :).
Stevethemacguy
4
Możesz sprawić, aby drzewo usług było wstrząsane, używając providedInatrybutu do zdefiniowania, gdzie usługa powinna zostać zainicjowana podczas korzystania z @Injectable()dekoratora. Następnie należy usunąć go z atrybutu dostawcy NgModuledeklaracji, a także instrukcji importu, co może pomóc w zmniejszeniu rozmiaru paczki poprzez usunięcie nieużywanego kodu z paczki.
nircraft
56

providedIn: 'root' to najłatwiejszy i najbardziej efektywny sposób świadczenia usług od czasu Angular 6:

  1. Usługa będzie dostępna dla całej aplikacji jako singleton bez konieczności dodawania jej do tablicy dostawców modułu (np. Angular <= 5).
  2. Jeśli usługa jest używana tylko w module ładowanym z opóźnieniem, będzie ładowana z opóźnieniem w tym module
  3. Jeśli nigdy nie zostanie użyty, nie zostanie uwzględniony w kompilacji (drzewo potrząśnie).

Aby uzyskać dalsze informacje, rozważ przeczytanie dokumentacji i często zadawanych pytań dotyczących NgModule

Przy okazji:

  1. Jeśli nie chcesz, aby singleton obejmujący całą aplikację, zamiast tego użyj tablicy składnika dostawcy.
  2. Jeśli chcesz ograniczyć zakres, aby żaden inny programista nigdy nie używał Twojej usługi poza określonym modułem, providerszamiast tego użyj tablicy NgModule.
Mick
źródło
Wspaniałe wyjaśnienie, dziękuję!
Nicolae Olariu
prosty, gwiezdny i bezpośredni!
petrosmm
Pytanie! Moja usługa z pewnością będzie polegać na innych usługach (poprzez DI w swoim konstruktorze). Wcześniej wszystkie zależności byłyby zarządzane w module świadczącym usługę ... A teraz? Zwłaszcza jeśli opiera się na bibliotece innej firmy (nie korzysta z usługi providedIn: root), jak sobie radzimy?
Bob
44

Z Dokumentów

Co to jest dekorator iniekcyjny?

Oznacza klasę jako dostępną dla wtryskiwacza do utworzenia.

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

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

Sama usługa jest klasą wygenerowaną przez CLI i udekorowaną za pomocą @Injectable ().

Co dokładnie zapewnia?

Określa, które wtryskiwacze będą dostarczać wstrzykiwacz, kojarząc go z @NgModule lub innym typem wtryskiwacza, albo określając, że ten wstrzykiwacz powinien być dostarczony we wtryskiwaczu „root”, który w większości aplikacji będzie wtryskiwaczem na poziomie aplikacji.

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

providedIn: 'root'

Kiedy udostępniasz usługę na poziomie głównym, Angular tworzy pojedyncze, współużytkowane wystąpienie usługi i wstrzykuje je do dowolnej klasy, która o to prosi. Zarejestrowanie dostawcy w metadanych @Injectable () umożliwia również Angularowi optymalizację aplikacji przez usunięcie usługi ze skompilowanej aplikacji, jeśli nie jest używana.

providedIn: Moduł

Możliwe jest również określenie, że usługa powinna być świadczona w określonym @NgModule. Na przykład, jeśli nie chcesz, aby usługa była dostępna dla aplikacji, chyba że zaimportują utworzony przez Ciebie moduł, możesz określić, że usługa ma być świadczona w module

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

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

Ta metoda jest preferowana, ponieważ umożliwia potrząsanie drzewem (potrząsanie drzewem jest krokiem w procesie budowania, który usuwa nieużywany kod z bazy kodu ) usługi, jeśli nic jej nie wstrzykuje.

W przypadku braku możliwości określenia w serwisie, który moduł ma to świadczyć, możesz również zadeklarować dostawcę usługi w ramach modułu:

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

@NgModule({
  providers: [UserService],
})
export class UserModule {
}
Nipuna
źródło
5
Najlepsze wyjaśnienie.
nop
3
ta odpowiedź jest lepsza niż definicja w dok. angular. bardzo czyste.
Shameera Anuranga
2
Bardzo dobrze wyjaśnione, bardzo dziękuję!
Zaki Mohammed
A co, gdy jest pusty, na przykład @Injectable()?
Ben Taliadoros
14

providedIn informuje Angular, że iniektor główny jest odpowiedzialny za utworzenie wystąpienia Twojej usługi. Usługi świadczone w ten sposób są automatycznie udostępniane całej aplikacji i nie muszą być wymienione w żadnym module.

Klasy usług mogą działać jako ich własne dostawcy, dlatego zdefiniowanie ich w dekoratorze @Injectable to jedyna rejestracja, jakiej potrzebujesz.

Jawad Farooqi
źródło
4

Zgodnie z Documentation:

Zarejestrowanie dostawcy w metadanych @Injectable () umożliwia również Angularowi optymalizację aplikacji przez usunięcie usługi ze skompilowanej aplikacji, jeśli nie jest używana.

Maarti
źródło
1

zobacz Doskonałe wyjaśnienie @Nipuna,

Chciałbym go rozszerzyć o przykłady.

jeśli używasz dekoratora do wstrzykiwań bez providedinwłaściwości, takich jak,

@Injectable()

wtedy musiałbyś wpisać nazwę usługi w odpowiedniej providerstablicy modułu .

lubię to;

data.service.ts ↴

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

@Injectable()
export class DataService {
    constructor() {}

    // Code . . .
}

app.module.ts ↴

import { AppComponent } from './app.component';
import { DataService } from './core/data.service';

@NgModule({
    declarations: [AppComponent],
    providers: [DataService],    // ⟵ LOOK HERE WE PROVIDED IT
    imports: [...],
    bootstrap: [AppComponent],
})
export class AppModule {}

Ale jeśli używasz providedIn: 'root', w ten sposób:

data.service.ts ↴

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

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

    // Code . . .
}

Wtedy nasz moduł wyglądałby tak:

app.module.ts ↴

import { AppComponent } from './app.component';
import { DataService } from './core/data.service';

@NgModule({
    declarations: [AppComponent],
    providers: [],
    imports: [...],
    bootstrap: [AppComponent],
})
export class AppModule {}

zobaczyć ja did't dodać DataServicew providerstablicy ten czas, bo to nie jest potrzebne.

Kokaina
źródło