angularjs internals angularjs-injector

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.