2015-02-20 6 views
11

Проблема проста: используя AngularJS, мы не можем вводить $ log в провайдера.

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

Да, мы можем придать $logProvider, но не имеет необходимых методов (.log, .error и т.д.).

Да, мы можем ввести $logProvider, а затем вручную позвонить $logProvider.$get(), но мы не сможем использовать дополнительную логику от декораторов.

Да, мы можем написать собственный logProvider, но мне интересно, почему Angular не поддерживает эту функцию из коробки.

Итак, мы не можем использовать консоль в режиме «истинный угловой путь» в провайдере? Этот факт очень странный. И грустно.

Вопрос: как мне нужно использовать консоль в «истинном угловом пути» в провайдерах?

Мне не удалось найти объяснений по данной проблеме. Руководство Angular Developers Guide говорит, что нам нужно использовать $ log везде, а не консоль.

ответ

14

Провайдеры работать слишком рано, прежде чем будут созданы какие-либо услуги, или другими словами провайдера $ получаете конструктор услуг и получает экземпляр после фазы конфигурации модуля (и когда она доступна в первый раз через зависимость инъекция инжектора создает экземпляр конструктора и сохраняет его как одиночный). И провайдеры работают во время или до фазы конфигурации (поскольку методы провайдера используются для настройки службы во время фазы модуля config). Это означает, что услуга $ log пока недоступна.

$logProvider.$get даст вам конструктор logservice, вы можете самостоятельно создать экземпляр этого, вызывая $injector.instantiate($logProvider.$get), но проблема в том, что она имеет зависимость от окна обслуживания, которое не пчела инстанцированный еще, так что в конечном итоге ваш регистратор конкретизации потерпит неудачу ,

Так что один из способов, о котором я только мог подумать, - получить $ log от другого инжектора, то есть angular.injector(['ng']).get('$log').

т.е.

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

Или другой способ просто клинит его экземпляр по своему усмотрению, инстанцировании зависимых служб в данном случае это просто $ окно (или даже обеспечить глобальное окно объект как местный житель).

.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

Просто, чтобы добавить другую заметку: Вы увидите такое же поведение при попытке получить доступ к $log службы на этапе настройки в приложении, а также. Но иногда из-за работы decorators вы все равно можете использовать ее, заставляя раннее создание службы использовать фиктивный декоратор.

т.е.

.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

Так в конечном счете идея заключается в том, что, когда вам нужно использовать службу, прежде чем он был создан экземпляр еще, вам нужно вручную создать его экземпляр путем разрешения все его зависимости и так далее.

+0

Просто добавьте к этому, что этот '$ log' будет другим экземпляром, чем тот, который будет введен в приложение. С '$ log' это может быть неважно, но если бы это была другая услуга, это могло бы быть –

+0

@PSL,' angular.injector (['ng']). Get ('$ log') '- приятное решение! (мы все еще теряем логику от пользовательских декораторов, но я придумываю этот печальный факт). Но ты не отвечаешь на мой вопрос. Я думаю, что пользователь ** должен ** иметь возможность использовать $ log (или что-то) в разделах поставщиков и конфигураций. Вы думаете, что для этой проблемы нет «истинного углового» решения? Что-то вроде собственного метода Angular.log(). –

+0

@harryburns Честно говоря, я не должен был делать многое в этих блоках. Если вообще использовать console.log .. каким-либо образом вы не можете действительно использовать di, введя в него $ log service сам, так что в чем смысл .. и нет никаких статических функций журнала, доступных в угловом режиме. – PSL

0

Вы можете написать службу обертки сказать регистратор, который может иметь методы, такие как журнал, предупреждает, отладку и т.д. и ввести свой сервис регистратора, где требуется Вы можете сделать форматирование там

например: Ниже метода находится внутри моего регистратора службы, чтобы вызвать этот метод только для ввода журнала и метода журнала вызовов.

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