Не удается извлечь инжектор из angular
У меня есть это приложение с двумя модулями:
angular.module('components', []).directive('foo', function () { return {};});
angular.module('gaad', ['components']);
Существует множество директив, связанных с этими модулями, которые я здесь не включаю.
Приложение работает нормально. Однако когда я пытаюсь извлечь инжектор для модуля gaad
:
var injector = angular.injector(['gaad', 'components']); //called after 'gaad' module initialization
выдается ошибка:
Uncaught Error: Unknown provider: $compileProvider from components
Приложение довольно большое прямо сейчас, и я понятия не имею, где искать ошибки.
Итак, мой вопрос: Что может быть причиной моих проблем?
EDIT:
Я смог реплицировать свою проблему: http://jsfiddle.net/selbh/ehmnt/11/
Ответы
Ответ 1
Прежде чем ответить на вопрос, мы должны отметить, что существует только один экземпляр инжектора для каждого приложения, а не для модуля. В этом смысле невозможно получить инжектор на модуль. Конечно, если мы возьмем модуль верхнего уровня, он будет представлять все приложение. В этом смысле приложение и модуль верхнего уровня кажутся эквивалентными. Это может показаться тонкой разницей, но важно понять, чтобы полностью и правильно ответить на этот вопрос.
Далее, из того, что я могу понять, вы хотели бы получить $injector
, а не создать новый экземпляр. Дело в том, что angular.injector
создаст новый экземпляр $injector
для модулей (приложения), указанных в качестве аргументов. Здесь главный модуль AngularJS (ng) должен быть указан явно. Итак, в этом примере кода:
var injector = angular.injector(['gaad', 'components']);
вы пытались создать новый инжектор из компонентов, определенных в модулях "gaad" и "components", и, очевидно, $compileProvider
не определен в ваших настраиваемых модулях. Добавление модуля ng
в список "решит" проблему, создав новый инжектор - что-то, чего вы, вероятно, не захотите.
Чтобы действительно получить экземпляр инжектора, связанный с запущенным приложением, мы можем использовать 2 метода:
Вот jsFiddle, показывающий 2 метода извлечения инжектора: http://jsfiddle.net/xaQzb/
Также обратите внимание, что использование $injector
напрямую не является очень распространенным сценарием вне модульного тестирования. Возможно, было бы полезно подумать о том, чтобы получить услуги AngularJS из-за пределов мира AngularJS. Подробнее здесь: Вызвать Angular JS из устаревшего кода.
Ответ 2
Кажется, вам нужно включить ng в инжектор.
var injector = angular.injector(['ng', 'b', 'a']);
От: AngularJS: инжектор
Модуль ng должен быть явно добавлен.
Ответ 3
Проблема заключается в потоке выполнения кода Angular. Чтобы интегрировать ответы @pkozlowski.opensource и соответствующие комментарии, обратите внимание, что свойство $injector
становится доступным для элементов DOM после выполнения кода модуля, так что когда вы получаете доступ к свойству (как при попытке console.log
его) свойство все равно будет undefined
.
Вы можете решить эту проблему, просто установив 0 тайм-аут на выполнение функции ведения журнала (т.е. не требуется явная задержка в миллисекундах). Этот хак работает, потому что функция регистрации будет выполняться, когда стек пуст, то есть когда завершена перезагрузка Angular, и свойство $injector
доступно для элементов DOM.
Другим (возможно, лучшим) решением в Angular lingo будет включение вашего $injector
-ассингового кода в блок запуска (см. также связанный API). Затем $injector
можно легко ввести в функцию инициализации как обычную службу. Это работает, потому что блоки запуска ставятся в очередь и выполняются асинхронно, когда завершается вся загрузка.
Ниже вы можете найти два скрипта, по одному для каждого решения.
0 Тайм-аут jsFiddle
Запустить блок jsFiddle
ИЗМЕНИТЬ
Кроме того, обычно нет необходимости явно загружать модуль ng
. В обычных случаях модель ng
уже загружена автоматически, если вы не хотите выполнять ручную загрузку кода Angular. Часть документов, на которые ссылается в одном из ответов, ссылается (неявно, к сожалению) на процедуру ручной загрузки w00 > , когда вам нужно вручную создать инжектор и сказать, какие модули вы хотите загрузить