Модули и конфликты имен/имен в AngularJS
Рассмотрим следующий jfiddle http://jsfiddle.net/bchapman26/9uUBU/29/
//angular.js example for factory vs service
var app = angular.module('myApp', ['module1', 'module2']);
var service1module = angular.module('module1', []);
service1module.factory('myService', function() {
return {
sayHello: function(text) {
return "Service1 says \"Hello " + text + "\"";
},
sayGoodbye: function(text) {
return "Service1 says \"Goodbye " + text + "\"";
}
};
});
var service2module = angular.module('module2', []);
service2module.factory('myService', function() {
return {
sayHello: function(text) {
return "Service2 says \"Hello " + text + "\"";
},
sayGoodbye: function(text) {
return "Service2 says \"Goodbye " + text + "\"";
}
};
});
function HelloCtrl($scope, myService) {
$scope.fromService1 = myService.sayHello("World");
}
function GoodbyeCtrl($scope, myService) {
$scope.fromService2 = myService.sayGoodbye("World");
}
У меня есть 2 модуля (module1 и module2). Оба модуля1 и module2 определяют службу myService. Кажется, создается конфликт имен в myService в Angular, когда оба модуля импортируются в myApp. Похоже, что AngularJs просто использует второе определение сервиса, не предупредив вас о возможной проблеме.
Очень большие проекты (или просто повторное использование модулей в целом) могут столкнуться с риском столкновения имен, что может быть сложно отлаживать.
Есть ли способ префиксных имен с именем модуля, чтобы не произошло столкновений имен?
Ответы
Ответ 1
На сегодняшний день модули AngularJS не предоставляют каких-либо пространств имен, которые предотвратили бы столкновения между объектами в разных модулях. Причина в том, что приложение AngularJS имеет один инжектор, который содержит имена для всех объектов без учета имен модулей.
Руководство разработчика AngularJS говорит:
Чтобы управлять ответственностью за создание зависимостей, каждый Angularприложение имеет инжектор. Инжектор - это локатор обслуживания, который ответственный за строительство и поиск зависимостей.
Как вы уже упоминали, неприятные ошибки могут возникнуть при вводе модулей в ваш основной модуль/приложение. Когда происходят столкновения, они молчат, и победитель определяется тем, какой последний модуль был введен.
Так нет, нет встроенного способа избежать этих столкновений. Возможно, это произойдет в будущем. Для крупных приложений, где эта проблема становится более вероятной, вы правы, что соглашения об именах - ваш лучший инструмент. Рассмотрим, могут ли объекты, принадлежащие модулю или области функций, использовать короткий префикс.
Ответ 2
Вы можете избежать этой ситуации, используя соглашение для обозначения своих модулей, чтобы они всегда были уникальными.
Один из подходов - посмотреть, как это делают другие языки. Например, в Java "полное имя" класса основано на имени файла и его папке. Например, если у вас был файл Java Bitmap.java в папке MyArtStuff, полное имя класса было бы be MyArtStuff.Bitmap
Выключает AngularJS позволяет вам иметь точки (.) как часть имени вашего модуля, чтобы вы могли в принципе использовать соглашение о названии.
Например, если разработчик создал модуль под названием "ModuleA" в script "MainPage\Module1.js", он должен назвать свой модуль "MainPage.Module1.ModuleA". Поскольку каждый путь и имя файла уникальны в вашем приложении, ваше имя модуля будет уникальным.
Вам просто нужно заставить своих разработчиков следовать этому соглашению.
Обратите внимание, что, как отмечает Rockallite, это не поможет службам, контроллерам и т.д. с одинаковым именем в нескольких модулях. Но вы можете использовать аналогичный подход, чтобы получить результат и префикс имен этих элементов.
В идеале AngularJS будет иметь пространства имен, и в будущем это может произойти. До тех пор самое лучшее, что мы можем сделать, это делать то, что разработчики делали уже более 40 лет, прежде чем были созданы пространства имен и префикс наших элементов, которые мы можем наилучшим образом.
Ответ 3
Определите свои контроллеры в модуле, из которого вы хотите, чтобы служба была.
service2Module.controller("ServiceTwoCtrl", function(myService, $scope) {});