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
$provideservicio 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 delprovidermétodo en el$provideservicio, y puede obtener el$provideservicio solicitando que se inyecte en laconfigfunció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 nombradagreetingen cualquier función inyectable (como controladores, más sobre eso más adelante) y Angular llamará a la$getfunción del proveedor para devolver una nueva instancia del servicio. En este caso, lo que se inyectará es una función que toma unnameparámetro yalertun mensaje basado en el nombre. Podríamos usarlo así:Ahora aquí está el truco.
factory,,serviceyvalueson 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.providerversión) para nosotros. Literalmente, 100% no hay diferencia en las dos versiones.valuefunciona de la misma manera: si lo que devolviéramos de nuestra$getfunción (también conocida como nuestrafactoryfunción) es siempre exactamente igual, podemos escribir aún menos código usandovalue. Por ejemplo, dado que siempre devolvemos la misma función para nuestrogreetingservicio, también podemos usarlavaluepara 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$providermé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$injectorque se crea cuando se inicia por primera vez; puede obtenerlo inyectándose$injectoren cualquier función inyectable (sí, ¡$injectorsabe cómo inyectarse!)Una vez que lo haya hecho
$injector, puede obtener una instancia de un servicio definido al llamarlogetcon 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
invokemé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$getmétodos de los proveedores (también conocidos como lasfactoryfunciones de definición)Como
constantsysvaluesiempre 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
providemé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 enconfigsecciones de su aplicación para que pueda interactuar con ellos!Primero, Angular ejecuta su aplicación en dos fases: las fases
configyrun. Laconfigfase, 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. Larunfase, 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.configymyMod.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$provideen nuestro primer ejemplo de código. Sin embargo, lo que vale la pena destacar es que durante laconfigfase, solamente los proveedores pueden ser inyectadas (con la excepción de los servicios en elAUTOmodule--$providey$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
constants, dado que no se pueden cambiar, pueden inyectarse dentro de losconfigbloques (así es como difieren de losvalues). Se accede a ellos solo por su nombre (no esProvidernecesario el sufijo).Cada vez que define un proveedor para un servicio, ese proveedor recibe un nombre
serviceProvider, dondeserviceestá 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
setTextque podemos usar para personalizar nuestroalert; Podemos acceder a este proveedor en unconfigbloque para llamar a este método y personalizar el servicio. Cuando finalmente ejecutamos nuestra aplicación, podemos obtener elgreetingservicio 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
$controllerque 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
$controllerservicio (que a su vez usa el$injectorpara invocar la función de su controlador para que también inyecte sus dependencias).Filtros y Directivas
filterydirectivefunciona exactamente de la misma manera quecontroller;filterusa un servicio llamado$filtery su proveedor$filterProvider, mientras quedirectiveusa un servicio llamado$compiley su proveedor$compileProvider. Algunos enlaces:Según los otros ejemplos,
myMod.filterymyMod.directiveson atajos para configurar estos servicios.Entonces, para resumir, cualquier función con la que se llame
$injector.invokepuede 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
$controllery$filterpueden 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
configyrundiferencias 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