¿Cuál es el propósito de proporcionar el decorador inyectable al generar servicios en Angular 6?

136

Al generar servicios en la CLI angular, está agregando metadatos adicionales con una propiedad 'proporcionada en' con un valor predeterminado de 'raíz' para el decorador inyectable.

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

¿Qué hace exactamente provideIn? Supongo que esto está haciendo que el servicio esté disponible como un servicio singleton de tipo 'global' para toda la aplicación, sin embargo, ¿no sería más limpio declarar tales servicios en la matriz de proveedores del AppModule?

ACTUALIZAR:

Para cualquier otra persona, el siguiente párrafo también proporcionó otra buena explicación, en particular si desea brindar su servicio solo a un módulo de funciones.

Ahora hay una nueva forma recomendada de registrar un proveedor, directamente dentro del @Injectable()decorador, utilizando el nuevo providedIn atributo. Acepta 'root'como valor o cualquier módulo de su aplicación. Cuando lo use 'root', injectablese registrará como un singleton en la aplicación, y no necesita agregarlo a los proveedores del módulo raíz. Del mismo modo, si lo usa providedIn: UsersModule, injectablese registra como un proveedor de la UsersModulesin agregarlo a la providersdel módulo. "- https://blog.ninja-squad.com/2018/05/04/what-is-new-angular -6 /

ACTUALIZACIÓN 2:

Después de una investigación más profunda, he decidido que solo es útil tener providedIn: 'root'

Si desea provideun servicio en cualquier módulo que no sea el módulo raíz, es mejor que use la providersmatriz en los decoradores del módulo de funciones, de lo contrario, estará plagado de dependencias circulares. Discusiones interesantes que se tendrán aquí - https://github.com/angular/angular-cli/issues/10170

Stefan Zvonar
fuente
17
Creo que sus actualizaciones deberían ser una respuesta (puede responder sus propias preguntas) en lugar de agregarlas a su pregunta.
PhoneixS
La parte más importante es SINGLETON, ¡nadie lo menciona!
Kyle Burkett

Respuestas:

54

si usa "provideIn", el inyectable se registra como proveedor del Módulo sin agregarlo a los proveedores del módulo.

De Docs

El servicio en sí es una clase que la CLI generó y que está decorada con @Injectable. Por defecto, este decorador está configurado con una propiedad provideIn, que crea un proveedor para el servicio. En este caso, provideIn: 'root' especifica que el servicio se debe proporcionar en el inyector raíz.

Sajeetharan
fuente
44
Gracias Sajeetharan De acuerdo, parece que es una nueva forma de acceso directo para especificar dónde se debe proporcionar el servicio. Supongo que mi preferencia inicial habría sido mirar la lista de proveedores de un módulo para ver todos los servicios que se declaran como proveedores, en lugar de examinar la base de código disperso para las etiquetas ProvidedIn ... (?)
Stefan Zvonar
2
¿Había alguna razón para que Angular agregara esto? ¿Hay algún problema que esto esté resolviendo? No veo que haya una razón para esto.
prolink007
3
Mantiene la definición de AppModule / CoreModule un poco más pequeña;)
Stefan Zvonar
22
@ prolink007. El uso de provideIn permite que la aplicación cargue lentamente los servicios. Para probar esto, coloque registros de consola en sus servicios. Mi página de inicio solía cargar 16 servicios, ahora carga 9. Es difícil cuantificar el rendimiento, pero me siento mejor sabiendo que no estoy cargando servicios hasta que sean necesarios :).
Stevethemacguy
3
Puede hacer que sus servicios se puedan sacudir utilizando el providedInatributo para definir dónde se debe inicializar el servicio al usar el @Injectable()decorador. Luego, debe eliminarlo del atributo de proveedores de su NgModuledeclaración, así como de su declaración de importación. Esto puede ayudar a reducir el tamaño del paquete eliminando el código no utilizado del paquete.
nircraft
48

providedIn: 'root' es la forma más fácil y eficiente de proporcionar servicios desde Angular 6:

  1. El servicio estará disponible en toda la aplicación como un singleton sin necesidad de agregarlo a la matriz de proveedores de un módulo (como Angular <= 5).
  2. Si el servicio solo se usa dentro de un módulo con carga lenta, se cargará con ese módulo
  3. Si nunca se usa, no se incluirá en la compilación (árbol sacudido).

Para obtener más información, considere leer la documentación y las preguntas frecuentes de NgModule

Por cierto:

  1. Si no desea un singleton para toda la aplicación, use la matriz de un componente del proveedor.
  2. Si desea limitar el alcance para que ningún otro desarrollador use su servicio fuera de un módulo en particular, use la providersmatriz de NgModule en su lugar.
Mick
fuente
37

De documentos

¿Qué es el decorador inyectable?

Marca una clase como disponible para Injector para su creación.

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

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

El servicio en sí es una clase que la CLI generó y que está decorada con @Injectable ().

¿Qué hace exactamente provideIn?

Determina qué inyectores proporcionarán el inyectable, ya sea asociandolo con un @NgModule u otro InjectorType, o especificando que este inyectable se debe proporcionar en el inyector 'raíz', que será el inyector de nivel de aplicación en la mayoría de las aplicaciones.

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

provideIn: 'root'

Cuando proporciona el servicio en el nivel raíz, Angular crea una única instancia de servicio compartida y la inyecta en cualquier clase que lo solicite. El registro del proveedor en los metadatos @Injectable () también permite a Angular optimizar una aplicación al eliminar el servicio de la aplicación compilada si no se utiliza.

provideIn: Módulo

También es posible especificar que se debe proporcionar un servicio en un @NgModule particular. Por ejemplo, si no desea que un servicio esté disponible para las aplicaciones a menos que importen un módulo que haya creado, puede especificar que el servicio se brinde en el módulo

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

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

Se prefiere este método porque permite la sacudida del árbol (la sacudida del árbol es un paso en un proceso de compilación que elimina el código no utilizado de una base de código ) del servicio si nada lo inyecta.

Si no es posible especificar en el servicio qué módulo debe proporcionarlo, también puede declarar un proveedor para el servicio dentro del módulo:

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

@NgModule({
  providers: [UserService],
})
export class UserModule {
}
Nipuna
fuente
44
La mejor explicación
nop
2
Esta respuesta es mejor que la definición en angular doc. muy claro.
Shameera Anuranga
2
Muy bien explicado, muchas gracias!
Zaki Mohammed
¿Qué pasa cuando está vacío, como @Injectable()?
Ben Taliadoros
13

provideIn le dice a Angular que el inyector raíz es responsable de crear una instancia de su Servicio. Los servicios que se brindan de esta manera se ponen automáticamente a disposición de toda la aplicación y no es necesario enumerarlos en ningún módulo.

Las clases de servicio pueden actuar como sus propios proveedores, por lo que definirlas en el decorador @Injectable es todo el registro que necesita.

Jawad Farooqi
fuente
4

De acuerdo con el Documentation:

El registro del proveedor en los metadatos @Injectable () también permite a Angular optimizar una aplicación al eliminar el servicio de la aplicación compilada si no se utiliza.

Maarti
fuente