2015-04-24 2 views
3

Я, конечно, не хватает какой принципиальный момент относительно инжектора, но я не понимаю, почему именно этот

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

и это

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

работы по назначению, в то время как это

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

выбросит

Error: [$injector:unpr] Unknown provider: $provideProvider <- $provide

Как следует из сказанного выше, config имеет некоторые особые отношения с поставщиками, в то время как run сделок с экземплярами, но я не уверен о то, что делает config блоки таким особенным.

В результате этого нет способа добраться до $provide за пределами config блоков, например. с angular.injector() (хотя кажется, что он также получает экземпляры провайдера)?

Вопрос, помимо простого любопытства, также имеет некоторые практические соображения. В 1.4 все функции $provide выставлены модулю, но это не относится к 1.3.

ответ

3

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

По существу, $injectorin config blocks and provider constructor functions и $injectoreverywhere else две разные услуги с таким же названием, которые определены на внутреннем поставщика/кэша экземпляра в явном виде, вместе с $provide (это один определяется в кэше провайдера, следовательно, он может быть введен в config).

В то время как правило, не рекомендуется из-за возможные условия гонки, можно выставить внутренние услуги в кэш экземпляра и сделать конфигурации конкретных $provide и $injector для инъекций после фазы конфигурации закончилась:

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

Возможного приложения настройки поставщиков услуг в любое время (если это возможно)

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

и определения новых компонентов во время выполнения

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

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

Что делает поставщиков «особенными» в том, что у них есть две части инициализации, и одна из них напрямую связана с блоком config(). Взгляните на следующий код:

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

Когда Вы вводите поставщика в функцию config(), вы можете получить доступ что-нибудь но$get функцию (технически вы можете получить доступ к функции $get, но называть его не будет Работа). Таким образом, вы можете выполнить любую конфигурацию, которая вам может понадобиться. Это первая часть инициализации. Стоит отметить, что хотя наш сервис называется myService, здесь вы должны использовать суффикс Provider.

Но когда вы вводите одного и того же провайдера в любое другое место, Angular вызывает функцию $get() и вводит все, что возвращается. Это вторая часть инициализации. В этом случае провайдер ведет себя как обычный сервис.

Теперь про $provide и $injector. Поскольку они являются «службами конфигурации», для меня имеет смысл, что вы не можете получить к ним доступ за пределами блока config(). Если бы вы могли, то вы могли бы, например, создать завод после, он был использован другой службой.

Наконец, я еще не играл с v1.4, поэтому я понятия не имею, почему это поведение, по-видимому, изменилось. Если кто-нибудь знает, почему, пожалуйста, дайте мне знать, и я уточню свой ответ.

+0

Спасибо, Майкл, это качественный ответ, который хорошо послужит сообществу. В настоящее время я немного продвинулся дальше и не могу узнать ничего нового из ответа. Я надеялся, что кто-то поделится своими знаниями с внутренними силами. Думаю, мне нужно пройти «бутстрап» и «инжектор» и изучить их еще раз. – estus

+0

В 1.4 'module', наконец, предоставляет весь API, который предоставляет' $ provision'. Это было не так в предыдущих версиях («декоратор» отсутствовал, по крайней мере). – estus

Смежные вопросы