angularjs - $ proporcionar bloques de configuración externos
internals angularjs-injector (2)
Después de un estudio de inyector angular pude dar una respuesta exhaustiva a mi propia pregunta.
Esencialmente,
$injector
en bloques de
config
y funciones de constructor de
provider
y
$injector
cualquier otro lugar
son dos servicios diferentes con el mismo nombre, que se definen explícitamente en la caché interna del proveedor / instancia, junto con
$provide
(esta se está definiendo en la caché del proveedor, por lo tanto, se puede inyectar solo en la
config
).
Aunque generalmente no se recomienda debido a las probables condiciones de carrera, es posible exponer los servicios internos a la caché de instancias y hacer que
$provide
y
$injector
específicos de configuración estén disponibles para inyección después de que la fase de configuración haya finalizado:
app.config(function ($provide, $injector) {
$provide.value(''$providerInjector'', $injector);
$provide.value(''$provide'', $provide);
});
Las posibles aplicaciones están configurando proveedores de servicios en cualquier momento (si es posible)
app.run(function ($providerInjector) {
var $compileProvider = $providerInjector.get(''$compileProvider'');
...
});
y definiendo nuevos componentes en tiempo de ejecución
app.run(function ($provide) {
$provide.controller(...);
...
});
Ciertamente me falta algún punto fundamental sobre el inyector, pero no entiendo por qué exactamente esto
angular.module(''app'').config(function ($provide) {
...
});
y esto
angular.module(''app'').config(function ($injector) {
$injector.invoke(function ($provide) { ... });
});
trabajar según lo previsto, mientras que esto
app.run(function($provide) {
...
});
arrojará
Error: [$ inyector: unpr] Proveedor desconocido: $ provideProvider <- $ provide
Como se deduce de lo anterior,
config
tiene una relación especial con los proveedores, mientras que
run
tratos con instancias, sin embargo, no estoy seguro de lo que hace que los bloques de
config
sean tan especiales.
Como consecuencia de eso, ¿no hay forma de llegar a
$provide
fuera de los bloques de
config
, por ejemplo, con
angular.injector()
(aunque parece que también obtiene instancias de proveedor)?
La pregunta, además de la mera curiosidad, también tiene algunas consideraciones prácticas.
En 1.4 todas las funciones
$provide
están expuestas al módulo, pero eso no es cierto para 1.3.
El propósito de la función
config()
es permitirle realizar alguna configuración
global
que afectará a toda la aplicación, que incluye servicios, directivas, controladores, etc. Por eso, el bloque
config()
debe ejecutarse antes que cualquier otra cosa.
Pero, aún necesita una forma de realizar la configuración mencionada y ponerla a disposición del resto de la aplicación.
Y la forma de hacerlo es mediante el uso de
proveedores
.
Lo que hace que los proveedores sean "especiales" es que tienen dos partes de inicialización, y una de ellas está directamente relacionada con el bloque
config()
.
Echa un vistazo al siguiente código:
app.provider(''myService'', function() {
var self = {};
this.setSomeGlobalProperty = function(value) {
self.someGlobalProperty = value;
};
this.$get = function(someDependency) {
this.doSomething = function() {
console.log(self.someGlobalProperty);
};
};
});
app.config(function(myServiceProvider) {
myServiceProvider.setSomeGlobalProperty(''foobar'');
});
app.controller(''MyCtrl'', function(myService) {
myService.doSomething();
});
Cuando inyecta un proveedor en la función
config()
, puede acceder a cualquier cosa
menos a
la función
$get
(técnicamente puede acceder a la función
$get
, pero llamarla no funcionará).
De esa manera puede hacer cualquier configuración que necesite hacer.
Esa es la primera parte de inicialización.
Vale la pena mencionar que, aunque nuestro servicio se llama
myService
, debe usar el
Provider
sufijo aquí.
Pero cuando inyecta el mismo proveedor en cualquier otro lugar, Angular llama a la función
$get()
e inyecta todo lo que devuelve.
Esa es la segunda parte de inicialización.
En este caso, el proveedor se comporta como un servicio ordinario.
Ahora alrededor de
$provide
y
$injector
.
Como son "servicios de configuración", tiene sentido para mí que no pueda acceder a ellos fuera del bloque
config()
.
Si pudiera, entonces podría, por ejemplo, crear una fábrica
después de
haber sido utilizada por otro servicio.
Finalmente, todavía no he jugado con v1.4, así que no tengo idea de por qué ese comportamiento aparentemente ha cambiado. Si alguien sabe por qué, hágamelo saber y actualizaré mi respuesta.