2015-02-20 25 views
11

Il problema è semplice: utilizzando AngularJS non è possibile immettere $ accedere al provider.

angular.module('my.module', []) 
    .provider('myProvider', function ($log, $logProvider) { 
     $log.log("Aloha!"); // Unknown provider: $log 
     $logProvider.log("Hi!"); // undefined is not a function: $logProvider has no `log` method 
     this.$get = function($log) { 
      $log.log("Hello!"); // Everything is ok here 
     }; 
    }); 

Sì, siamo in grado di iniettare $logProvider, ma non ha metodi necessari (.log, .error, etc.).

Sì, è possibile iniettare $logProvider e quindi chiamare manualmente $logProvider.$get(), ma non sarà possibile utilizzare la logica aggiuntiva dai decoratori.

Sì, possiamo scrivere il nostro logProvider, ma mi chiedo perché Angular non supporta questa funzionalità immediatamente.

Quindi, non possiamo usare la console in 'modo angolare vero' nel provider? Questo fatto è molto strano. E triste.

La domanda: in che modo è necessario utilizzare la console in "modo angolare" nei provider?

Non sono riuscito a trovare alcuna spiegazione di questo problema. Angular Developers Guide dice che dobbiamo usare $ log ovunque anziché console.

risposta

14

Provider correre troppo presto prima che si creano tutti i servizi o in altre parole fornitore di $ ottenere è il costruttore di servizio e si ottiene un'istanza dopo la fase di configurazione del modulo (e quando si accede per la prima volta tramite la dipendenza iniezione l'iniettore istanzia il costruttore e lo mantiene come singleton). I provider vengono eseguiti durante o prima della fase di configurazione (poiché i metodi del provider vengono utilizzati per configurare il servizio durante la fase config del modulo). Il che significa che il servizio $ log non è ancora disponibile.

$logProvider.$get vi darà il costruttore per LOGSERVICE, si potrebbe te stesso crea un'istanza di esso chiamando $injector.instantiate($logProvider.$get), ma il problema è che ha una dipendenza sul servizio finestra che non ha bee ancora istanziato, quindi in ultima analisi, la vostra esemplificazione logger fallirà .

Quindi un modo che potrei pensare è di ottenere $ log da un altro iniettore, cioè angular.injector(['ng']).get('$log').

cioè

angular.module('my.module', []) 
    .provider('myProvider', function ($log, $logProvider) { 
    var $log = angular.injector(['ng']).get('$log'); 
    $log.log("Aloha!"); 

    this.$get = function($log) { 
     $log.log("Hello!"); // Everything is ok here 
    }; 
}); 

Plnkr

modo o nell'altro basta andare instantiate pazzo da soli, istanziare i suoi servizi dipendenti in questo caso è solo l'$ finestra (o addirittura fornire finestra globale oggetto come locale).

.provider('myProvider', function ($logProvider,$injector, $windowProvider) { 
    //get window service, if you want to really provide window service instance itself, or just provide the global window object 
    var window = $injector.instantiate($windowProvider.$get); 
    //Get log provider providing locals for $window 
    var $log = $injector.instantiate($logProvider.$get,{$window:window}) 

    $log.log("Aloha!");// Everything is ok here too 

    this.$get = function($log) { 
     $log.log("Hello!"); // Everything is ok here 
    }; 

}); 

Plnkr

solo per aggiungere una nota diversa: Si vedrà lo stesso comportamento durante il tentativo di accedere al servizio $log durante la fase di configurazione della app pure. Ma a volte, a causa del modo in cui funziona lo standard decorators, puoi ancora utilizzarlo forzando una creazione anticipata del servizio utilizzando un fittizio decoratore.

cioè:

.config(function($provide){ 
    //Just a dummy decorator 
    $provide.decorator('$log', function($delegate){ 
     return $delegate; 
    }); 

}).config(function($logProvider){ 
    //get logger instance 
    var log = $logProvider.$get(); 
    log.debug("Got it"); 
}); 

Plnkr

Quindi in ultima analisi, l'idea è che, quando è necessario utilizzare un servizio prima che sia stato ancora istanziato, si avrebbe bisogno di istanziare manualmente risolvendo tutte le sue dipendenze e così via.

+0

Solo per aggiungere a questo, che questo '$ log' sarà un'istanza diversa da quella che verrebbe iniettata nell'app. Con '$ log' potrebbe non essere importante, ma se fosse un servizio diverso, potrebbe –

+0

@PSL,' angular.injector (['ng']). Get ('$ log') 'è una bella soluzione! (perdiamo ancora la logica dai decoratori personalizzati, ma mi sto prendendo cura di questo fatto triste). Ma tu non rispondi alla mia domanda. Penso che l'utente ** dovrebbe ** essere in grado di utilizzare $ log (o qualcosa) nelle sezioni provider e config. Pensi che non ci sia una soluzione "vera angolare" per questo problema? Qualcosa come il metodo Angular.log() nativo. –

+0

@harryburns Francamente ho dovuto fare molte registrazioni in quei blocchi. Se proprio non usi console.log .. in qualsiasi modo tu non possa veramente usare di iniettando il servizio $ log stesso là fuori, quindi qual è il punto .. e non ci sono funzioni di registro statico disponibili in angolare. – PSL

0

È possibile scrivere un servizio involucro dire logger che può avere metodi come log, avvisare, eseguire il debug ecc e iniettare il servizio logger ovunque necessario, è possibile fare la formattazione ci

esempio: Sotto metodo è dentro il mio logger servizio per richiamare questo logger appena iniettato e il metodo del registro delle chiamate.

this.log = function() { 
     if (this.debuggingEnabled) { 
      for (var i = 1; i < arguments.length; i++) { 
       $log.log("[" + $filter('date')(new Date(), this.format) + "] -- " + arguments[0] + " -- " + JSON.stringify(arguments[i])); 
      } 
     } 
    }; 
Problemi correlati