Me está costando un poco entender la inyección de dependencia en angular. Entonces mi pregunta es, ¿alguien puede explicar cuál de los "tipos", como Controlador, Fábrica, Proveedor, etc., podemos inyectar en otros, incluidas otras instancias del mismo "tipo"?
Lo que realmente estoy buscando es esta tabla llena de y / n. Para celdas con la misma fila / columna, eso significa inyectar el valor de un "tipo" en otro con el mismo "tipo"
+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+
| Can we inject? | Constant | Controller | Directive | Factory | Filter | Provider | Service | Value |
+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+
| Constant | | | | | | | | |
| Controller | | | | | | | | |
| Directive | | | | | | | | |
| Factory | | | | | | | | |
| Filter | | | | | | | | |
| Provider | | | | | | | | |
| Service | | | | | | | | |
| Value | | | | | | | | |
+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+
angularjs
dependency-injection
usuario1527166
fuente
fuente
Respuestas:
En lugar de eso, simplemente llene la tabla con "sí" y "no" sin explicación, voy a entrar en un poco más de detalle.
[Nota, agregada después de terminar: esto terminó siendo ... bastante más largo de lo que esperaba. Hay un tl; dr en la parte inferior, pero espero que esto sea informativo.]
[Esta respuesta también se ha agregado a la wiki de AngularJS: comprensión de la inyección de dependencia ]
El proveedor (
$provide
)El
$provide
servicio es responsable de decirle a Angular cómo crear nuevas cosas inyectables; Estas cosas se llaman servicios . Los servicios se definen por cosas llamadas proveedores , que es lo que estás creando cuando las usas$provide
. La definición de un proveedor se realiza a través delprovider
método en el$provide
servicio, y puede obtener el$provide
servicio solicitando que se inyecte en laconfig
función de una aplicación . Un ejemplo podría ser algo como esto:Aquí hemos definido un nuevo proveedor para un servicio llamado
greeting
; podemos inyectar una variable nombradagreeting
en cualquier función inyectable (como controladores, más sobre eso más adelante) y Angular llamará a la$get
función del proveedor para devolver una nueva instancia del servicio. En este caso, lo que se inyectará es una función que toma unname
parámetro yalert
un mensaje basado en el nombre. Podríamos usarlo así:Ahora aquí está el truco.
factory
,,service
yvalue
son solo accesos directos para definir varias partes de un proveedor, es decir, proporcionan un medio para definir un proveedor sin tener que escribir todo eso. Por ejemplo, podría escribir exactamente ese mismo proveedor así:Es importante entenderlo, así que lo reformularé: bajo el capó, AngularJS está llamando exactamente el mismo código que escribimos anteriormente (la
$provide.provider
versión) para nosotros. Literalmente, 100% no hay diferencia en las dos versiones.value
funciona de la misma manera: si lo que devolviéramos de nuestra$get
función (también conocida como nuestrafactory
función) es siempre exactamente igual, podemos escribir aún menos código usandovalue
. Por ejemplo, dado que siempre devolvemos la misma función para nuestrogreeting
servicio, también podemos usarlavalue
para definirla:Nuevamente, esto es 100% idéntico a los otros dos métodos que hemos usado para definir esta función: es solo una forma de guardar algo de escritura.
Ahora probablemente notaste esta
app.config(function($provide) { ... })
cosa molesta que he estado usando. Dado que la definición de nuevos proveedores (a través de cualquiera de los métodos anteriores) es muy común, AngularJS expone los$provider
métodos directamente en el objeto del módulo, para ahorrar aún más tipeo:Todos estos hacen lo mismo que las
app.config(...)
versiones más detalladas que utilizamos anteriormente.El inyectable que me he saltado hasta ahora es
constant
. Por ahora, es bastante fácil decir que funciona igualvalue
. Veremos que hay una diferencia más tarde.Para revisar , todas estas piezas de código están haciendo exactamente lo mismo:
El inyector (
$injector
)El inyector es responsable de crear instancias de nuestros servicios utilizando el código que proporcionamos
$provide
(sin juego de palabras). Cada vez que escribe una función que toma argumentos inyectados, está viendo el inyector en funcionamiento. Cada aplicación AngularJS tiene un único$injector
que se crea cuando se inicia por primera vez; puede obtenerlo inyectándose$injector
en cualquier función inyectable (sí, ¡$injector
sabe cómo inyectarse!)Una vez que lo haya hecho
$injector
, puede obtener una instancia de un servicio definido al llamarloget
con el nombre del servicio. Por ejemplo,El inyector también es responsable de inyectar servicios en funciones; por ejemplo, puede inyectar servicios mágicamente en cualquier función que tenga usando el
invoke
método del inyector ;Vale la pena señalar que el inyector solo creará una instancia de un servicio una vez . Luego almacena en caché lo que el proveedor devuelve por el nombre del servicio; la próxima vez que solicite el servicio, obtendrá exactamente el mismo objeto.
Entonces, para responder a su pregunta, puede inyectar servicios en cualquier función que se llame
$injector.invoke
. Esto incluye$get
métodos de los proveedores (también conocidos como lasfactory
funciones de definición)Como
constant
sysvalue
siempre devuelven un valor estático, no se invocan a través del inyector y, por lo tanto, no puede inyectarles nada.Configurar proveedores
Usted puede preguntarse por qué alguien se molestaría en configurar un proveedor de pleno derecho con el
provide
método sifactory
,value
, etc, son mucho más fácil. La respuesta es que los proveedores permiten mucha configuración. Ya hemos mencionado que cuando crea un servicio a través del proveedor (o cualquiera de los accesos directos que Angular le brinda), crea un nuevo proveedor que define cómo se construye ese servicio. ¡Lo que no mencioné es que estos proveedores pueden inyectarse enconfig
secciones de su aplicación para que pueda interactuar con ellos!Primero, Angular ejecuta su aplicación en dos fases: las fases
config
yrun
. Laconfig
fase, como hemos visto, es donde puede configurar cualquier proveedor según sea necesario. Aquí también se configuran las directivas, los controladores, los filtros y similares. Larun
fase, como puede suponer, es donde Angular realmente compila su DOM e inicia su aplicación.Puede agregar código adicional para que se ejecute en estas fases con las funciones
myMod.config
ymyMod.run
, cada una toma una función para ejecutarse durante esa fase específica. Como vimos en la primera sección, estas funciones son inyectables: inyectamos el servicio incorporado$provide
en nuestro primer ejemplo de código. Sin embargo, lo que vale la pena destacar es que durante laconfig
fase, solamente los proveedores pueden ser inyectadas (con la excepción de los servicios en elAUTO
module--$provide
y$injector
).Por ejemplo, lo siguiente no está permitido :
A lo que sí tiene acceso es a cualquier proveedor de servicios que haya realizado:
Hay una excepción importante: los
constant
s, dado que no se pueden cambiar, pueden inyectarse dentro de losconfig
bloques (así es como difieren de losvalue
s). Se accede a ellos solo por su nombre (no esProvider
necesario el sufijo).Cada vez que define un proveedor para un servicio, ese proveedor recibe un nombre
serviceProvider
, dondeservice
está el nombre del servicio. ¡Ahora podemos usar el poder de los proveedores para hacer cosas más complicadas!Ahora tenemos una función en nuestro proveedor llamada
setText
que podemos usar para personalizar nuestroalert
; Podemos acceder a este proveedor en unconfig
bloque para llamar a este método y personalizar el servicio. Cuando finalmente ejecutamos nuestra aplicación, podemos obtener elgreeting
servicio y probarlo para ver que nuestra personalización entró en vigencia.Dado que este es un ejemplo más complejo, aquí hay una demostración de trabajo: http://jsfiddle.net/BinaryMuse/9GjYg/
Controladores (
$controller
)Las funciones del controlador pueden inyectarse, pero los controladores mismos no pueden inyectarse en otras cosas. Esto se debe a que los controladores no se crean a través del proveedor. En cambio, hay un servicio angular incorporado llamado
$controller
que es responsable de configurar sus controladores. Cuando llamamyMod.controller(...)
, en realidad está accediendo al proveedor de este servicio , al igual que en la última sección.Por ejemplo, cuando define un controlador como este:
Lo que realmente estás haciendo es esto:
Más tarde, cuando Angular necesita crear una instancia de su controlador, usa el
$controller
servicio (que a su vez usa el$injector
para invocar la función de su controlador para que también inyecte sus dependencias).Filtros y Directivas
filter
ydirective
funciona exactamente de la misma manera quecontroller
;filter
usa un servicio llamado$filter
y su proveedor$filterProvider
, mientras quedirective
usa un servicio llamado$compile
y su proveedor$compileProvider
. Algunos enlaces:Según los otros ejemplos,
myMod.filter
ymyMod.directive
son atajos para configurar estos servicios.Entonces, para resumir, cualquier función con la que se llame
$injector.invoke
puede inyectarse . Esto incluye, de su gráfico (pero no se limita a):$get
(cuando se define proveedor como un objeto)El proveedor crea nuevos servicios que pueden inyectarse en las cosas . Esto incluye:
Dicho esto, a los servicios integrados les gusta
$controller
y$filter
pueden inyectarse, y puede usar esos servicios para obtener los nuevos filtros y controladores que definió con esos métodos (a pesar de que las cosas que definió no son, por sí mismas, capaces de ser inyectado en las cosas).Aparte de eso, cualquier función inyector-invocado puede ser inyectado con cualquier servicio de proveedor-proporcionado - no hay ninguna restricción (aparte de la
config
yrun
diferencias aparecen en este documento).fuente
El punto que BinaryMuse hace en su increíble respuesta acerca de que los proveedores, las fábricas y los servicios son lo mismo extremadamente importante.
A continuación se muestra una imagen que creo que puede ilustrar visualmente su punto:
(fuente: simplygoodcode.com )
fuente
Gran respuesta de Michelle. Solo quiero señalar que se pueden inyectar directivas . Si tiene una directiva llamada
myThing
, puede inyectarlamyThingDirective
: Aquí hay un ejemplo artificial .El ejemplo anterior no es muy práctico, sin embargo, la capacidad de inyectar una directiva es útil cuando desea decorar esa directiva .
fuente