Мне все еще хотелось бы знать, как я мог найти место в нашем исходном коде, которое вызвало эту проблему, но с тех пор я смог найти проблему вручную.
В глобальной области видимости объявлена функция контроллера вместо использования .controller()
вызова модуля приложения.
Так получилось примерно так:
function SomeController( $scope, i18n ) { /* ... */ }
Это отлично работает для AngularJS, но для правильной работы с искажением мне пришлось изменить его на:
var applicationModule = angular.module( "example" );
function SomeController( $scope, i18n ) { /* ... */ }
applicationModule.controller( "SomeController", [ "$scope", "i18n", SomeController ] );
После дальнейших тестов я действительно обнаружил экземпляры большего количества контроллеров, которые также вызывали проблемы. Вот как я нашел их источник вручную :
Прежде всего, считаю очень важным включить украшение вывода в опциях uglify. Для нашей тяжелой задачи это означало:
options : {
beautify : true,
mangle : true
}
Затем я открыл веб-сайт проекта в Chrome с открытым DevTools. Это приводит к регистрации ошибки, подобной приведенной ниже:
Нас интересует метод трассировки вызовов, который я пометил стрелкой. Это providerInjector
вinjector.js
. Вам нужно разместить точку останова там, где она выдает исключение:
Теперь, когда вы повторно запустите приложение, будет достигнута точка останова, и вы сможете перепрыгнуть вверх по стеку вызовов. Будет звонок из invoke
ininjector.js
, узнаваемый по строке «Неправильный токен инъекции»:
locals
Параметр (подогнаны к d
в моем коде) дает довольно хорошее представление о том, какой объект в источнике является проблемой:
Быстрый просмотр grep
нашего источника обнаруживает много экземпляров modalInstance
, но, исходя из этого, было легко найти это место в источнике:
var ModalCreateEditMeetingController = function( $scope, $modalInstance ) {
};
Что нужно изменить на:
var ModalCreateEditMeetingController = [ "$scope", "$modalInstance", function( $scope, $modalInstance ) {
} ];
В случае, если переменная не содержит полезной информации, вы также можете перепрыгнуть вверх по стеку, и вы должны нажать вызов, invoke
который должен иметь дополнительные подсказки:
Предотвратить это снова
Теперь, когда вы, надеюсь, нашли проблему, я чувствую, что должен упомянуть, как лучше всего избежать повторения этого в будущем.
Очевидно, вы могли бы просто везде использовать аннотацию встроенного массива или $inject
аннотацию свойств (в зависимости от ваших предпочтений) и просто постараться не забывать об этом в будущем. Если вы это сделаете, обязательно включите режим строгой инъекции зависимостей , чтобы на раннем этапе отлавливать подобные ошибки.
Осторожно! Если вы используете Angular Batarang, StrictDI может не работать для вас, поскольку Angular Batarang вставляет неаннотированный код в ваш (плохой Batarang!).
Или вы можете позволить ng-annotate позаботиться об этом. Я настоятельно рекомендую сделать это, так как это устраняет множество ошибок в этой области, например:
- Аннотации DI отсутствуют
- Аннотации DI не завершены
- Аннотации DI в неправильном порядке
Обновление аннотаций - это просто головная боль, и вам не нужно этого делать, если это можно сделать автоматически. ng-annotate делает именно это.
Он должен хорошо интегрироваться в ваш процесс сборки с помощью grunt-ng-annotate и gulp-ng-annotate .