Qual é o objetivo de fornecido com o decorador injetável ao gerar serviços no Angular 6?

136

Ao gerar serviços na CLI Angular, ele adiciona metadados extras com uma propriedade 'fornecida em' com um padrão de 'raiz' para o decorador injetável.

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

O que exatamente o Fornecido faz? Suponho que isso esteja disponibilizando o serviço como um serviço singleton do tipo 'global' para todo o aplicativo; no entanto, não seria mais fácil declarar esses serviços na matriz de provedores do AppModule?

ATUALIZAR:

Para qualquer outra pessoa, o parágrafo a seguir também forneceu outra boa explicação, principalmente se você deseja fornecer seu serviço apenas a um módulo de recursos.

Agora existe uma nova maneira recomendada de registrar um provedor, diretamente dentro do @Injectable()decorador, usando o novo providedIn atributo. Ele aceita 'root'como um valor ou qualquer módulo do seu aplicativo. Ao usar 'root', você injectableserá registrado como um singleton no aplicativo e não precisará adicioná-lo aos provedores do módulo raiz. Da mesma forma, se você usar providedIn: UsersModule, ele injectableserá registrado como um provedor do UsersModulesem adicioná-lo ao providersmódulo. "- https://blog.ninja-squad.com/2018/05/04/what-is-new-angular -6 /

ATUALIZAÇÃO 2:

Após uma investigação mais aprofundada, decidi que só é útil ter providedIn: 'root'

Se você deseja provideum serviço em qualquer módulo que não seja o módulo raiz, é melhor usar a providersmatriz nos decoradores do módulo de recursos, caso contrário, você será atormentado por dependências circulares. Discussões interessantes a serem realizadas aqui - https://github.com/angular/angular-cli/issues/10170

Stefan Zvonar
fonte
17
Acho que suas atualizações devem ser uma resposta (você pode responder suas próprias perguntas) em vez de adicioná-las à sua pergunta.
precisa saber é o seguinte
A parte mais importante é SINGLETON, ninguém menciona!
precisa

Respostas:

54

se você usar o fornecido, o injetável é registrado como um provedor do Módulo sem adicioná-lo aos provedores do módulo.

De Docs

O serviço em si é uma classe gerada pela CLI e decorada com @Injectable. Por padrão, esse decorador é configurado com uma propriedade fornecida, que cria um provedor para o serviço. Nesse caso, fornecido em: 'root' especifica que o serviço deve ser fornecido no injetor de raiz.

Sajeetharan
fonte
4
Obrigado sajeetharan. Ok, parece que é uma nova maneira de especificar onde o serviço deve ser fornecido. Acho que a minha preferência inicial teria sido olhando para lista de provedores de um módulo para ver todos os serviços que são declaradas como prestadores de serviços, em vez de ler atentamente a base de código dispersa para tags ProvidedIn .... (?)
Stefan Zvonar
2
Havia alguma razão para a Angular adicionar isso? Existe um problema que isso está resolvendo? Não vejo que haja uma razão para isso.
prolink007
3
Mantém a AppModule / definição CoreModule um pouco menor;)
Stefan Zvonar
22
@ prolink007. O uso de allowedIn permite que os serviços sejam carregados com preguiça pelo aplicativo. Para testar isso, coloque os logs do console em seus serviços. Minha home page costumava carregar 16 serviços, agora carrega 9. É difícil quantificar o desempenho, mas me sinto melhor sabendo que não estou carregando serviços até que sejam necessários :).
Stevethemacguy
3
Você pode tornar seus serviços tremendos em árvore usando o providedInatributo para definir onde o serviço deve ser inicializado ao usar o @Injectable()decorador. Você deve removê-lo do atributo de fornecedores da sua NgModuledeclaração, bem como de sua declaração de importação. Isso pode ajudar a reduzir o tamanho do pacote removendo o código não utilizado do pacote.
Nircraft
48

providedIn: 'root' é a maneira mais fácil e eficiente de fornecer serviços desde o Angular 6:

  1. O serviço estará disponível em todo o aplicativo como um singleton, sem a necessidade de adicioná-lo à matriz de provedores de um módulo (como Angular <= 5).
  2. Se o serviço for usado apenas dentro de um módulo carregado lento, ele será carregado lentamente com esse módulo
  3. Se nunca for usado, não estará contido na compilação (árvore abalada).

Para mais informações, considere ler a documentação e as perguntas frequentes do NgModule

Btw:

  1. Se você não deseja um singleton para todo o aplicativo, use a matriz de um componente do provedor.
  2. Se você deseja limitar o escopo para que nenhum outro desenvolvedor use seu serviço fora de um módulo específico, use a providersmatriz do NgModule.
Mick
fonte
37

Do Documentos

O que é decorador injetável?

Marca uma classe como disponível para o Injector para criação.

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

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

O serviço em si é uma classe gerada pela CLI e decorada com @Injectable ().

O que exatamente o Fornecido faz?

Determina quais injetores fornecerão o injetável, associando-o a um @NgModule ou outro InjectorType, ou especificando que esse injetável deve ser fornecido no injetor 'root', que será o injetor no nível do aplicativo na maioria dos aplicativos.

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

fornecidoIn: 'root'

Quando você fornece o serviço no nível raiz, o Angular cria uma instância única e compartilhada do serviço e o injeta em qualquer classe que solicitar. O registro do provedor nos metadados @Injectable () também permite que o Angular otimize um aplicativo removendo o serviço do aplicativo compilado, se ele não for usado.

includedIn: Module

Também é possível especificar que um serviço deve ser fornecido em um @NgModule específico. Por exemplo, se você não deseja que um serviço esteja disponível para aplicativos, a menos que eles importem um módulo que você criou, você pode especificar que o serviço deve ser fornecido no módulo

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

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

Esse método é preferido porque habilita a agitação da árvore (a agitação da árvore é uma etapa de um processo de compilação que remove o código não utilizado de uma base de código ) do serviço se nada o injetar.

Se não for possível especificar no serviço qual módulo deve fornecê-lo, você também pode declarar um provedor para o serviço dentro do módulo:

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

@NgModule({
  providers: [UserService],
})
export class UserModule {
}
Nipuna
fonte
4
A melhor explicação.
nop
2
esta resposta é mais melhor que a definição no documento angular. muito claro.
Shameera Anuranga 10/09/19
2
Muito bem explicado, muito obrigado!
Zaki Mohammed
E quando está vazio, como @Injectable()?
Ben Taliadoros
13

fornecidoIn informa à Angular que o injetor raiz é responsável por criar uma instância do seu Serviço. Os serviços fornecidos dessa maneira são automaticamente disponibilizados para todo o aplicativo e não precisam ser listados em nenhum módulo.

As classes de serviço podem atuar como seus próprios provedores, e é por isso que defini-las no decorador @Injectable é todo o registro que você precisa.

Jawad Farooqi
fonte
4

De acordo com Documentation:

O registro do provedor nos metadados @Injectable () também permite que o Angular otimize um aplicativo removendo o serviço do aplicativo compilado, se ele não for usado.

Maarti
fonte