$ fornire blocchi di configurazione esterni

Mi manca sicuramente un punto fondamentale sull’iniettore, ma non riesco a capire perché esattamente questo

angular.module('app').config(function ($provide) { ... }); 

e questo

 angular.module('app').config(function ($injector) { $injector.invoke(function ($provide) { ... }); }); 

funziona come previsto, mentre questo

 app.run(function($provide) { ... }); 

getterà

Errore: [$ injector: unpr] Provider sconosciuto: $ provideProvider <- $ provide

    Come segue da quanto sopra, config ha qualche relazione speciale con i provider, mentre run transazioni con le istanze, eppure non sono sicuro della cosa che rende i blocchi di config così speciali.

    Di conseguenza, non c’è modo di ottenere $provide blocchi di config esterni, ad esempio con angular.injector() (anche se sembra che anche le istanze del provider)?

    La domanda, oltre alla semplice curiosità, ha anche alcune considerazioni pratiche. Nella versione 1.4 tutte le funzioni di offerta $provide sono esposte al modulo, ma ciò non è vero per 1.3.

    Lo scopo della funzione config() è di consentire di eseguire alcune configurazioni globali che interesseranno l’intera applicazione, inclusi servizi, direttive, controller, ecc. Per questo config() , il blocco config() deve essere eseguito prima di qualsiasi altra cosa. Ma hai ancora bisogno di un modo per eseguire la suddetta configurazione e renderla disponibile al resto dell’app. E il modo per farlo è usando i provider .

    Ciò che rende i provider “speciali” è che hanno due parti di inizializzazione e uno di essi è direttamente correlato al blocco config() . Dai un’occhiata al seguente codice:

     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(); }); 

    Quando si inietta un provider nella funzione config() , è ansible accedere a qualsiasi cosa tranne la funzione $get (tecnicamente è ansible accedere alla funzione $get , ma chiamarla non funzionerà). In questo modo puoi fare qualsiasi configurazione tu possa aver bisogno di fare. Questa è la prima parte di inizializzazione. Vale la pena ricordare che anche se il nostro servizio è chiamato myService , è necessario utilizzare il suffisso Provider qui.

    Ma quando si inserisce lo stesso provider in qualsiasi altro posto, Angular chiama la funzione $get() e inietta qualsiasi cosa ritorni. Questa è la seconda parte di inizializzazione. In questo caso, il provider si comporta come un normale servizio.

    Ora su $provide e $injector . Dato che sono “servizi di configurazione”, per me è logico che tu non possa accedervi al di fuori del blocco config() . Se tu potessi, allora potresti, ad esempio, creare una fabbrica dopo essere stata usata da un altro servizio.

    Infine, non ho ancora giocato con la v1.4, quindi non ho idea del perché questo comportamento sia apparentemente cambiato. Se qualcuno sa perché, per favore fatemelo sapere e aggiornerò la mia risposta.

    Dopo alcuni studi sugli iniettori angolari, sono riuscito a dare una risposta esaustiva alla mia domanda.

    Essenzialmente, $injector nei blocchi di config e nelle funzioni di costruzione del provider e $injector ovunque sono due servizi diversi con lo stesso nome, definiti esplicitamente sulla cache interna del provider / dell’istanza, insieme a $provide (questo viene definito nella cache del provider, quindi può essere iniettato solo in config ).

    Sebbene generalmente non consigliato a causa di probabili condizioni di gara, è ansible esporre i servizi interni alla cache di istanza e rendere disponibili $injector e $injector configurazione specifici per l’iniezione dopo la fase di configurazione:

     app.config(function ($provide, $injector) { $provide.value('$providerInjector', $injector); $provide.value('$provide', $provide); }); 

    Le possibili applicazioni stanno configurando i fornitori di servizi in qualsiasi momento (se ansible)

     app.run(function ($providerInjector) { var $compileProvider = $providerInjector.get('$compileProvider'); ... }); 

    e definire nuovi componenti in fase di esecuzione

     app.run(function ($provide) { $provide.controller(...); ... });