que - Módulos y espacio de nombres/colisión de nombres en AngularJS
modulos angularjs (4)
Considere el siguiente 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");
}
Tengo 2 módulos (módulo 1 y módulo 2). Tanto el módulo 1 como el módulo 2 definen un servicio llamado myService. Esto parece crear un conflicto de nombres en myService dentro de Angular cuando ambos módulos se importan a myApp. Parece que AngularJs solo usa la segunda definición de servicio sin avisarle del posible problema.
Los proyectos muy grandes (o simplemente reutilizando módulos en general) tendrían el riesgo de que los nombres entren en conflicto, lo que podría ser difícil de depurar.
¿Hay una manera de prefijar nombres con el nombre del módulo para que no se produzcan conflictos de nombres?
A partir de hoy, los módulos AngularJS no proporcionan ningún tipo de espacio de nombres que impida las colisiones entre objetos en diferentes módulos. La razón es que una aplicación AngularJS tiene un solo inyector que contiene nombres para todos los objetos sin tener en cuenta los nombres de los módulos.
La Guía del desarrollador de AngularJS dice:
Para gestionar la responsabilidad de la creación de dependencias, cada aplicación angular tiene un inyector. El inyector es un localizador de servicios que es responsable de la construcción y búsqueda de dependencias.
Como ha mencionado, pueden aparecer errores desagradables al inyectar módulos en su módulo principal / aplicación. Cuando ocurren colisiones, son silenciosas y el ganador está determinado por el último módulo inyectado.
Así que no, no hay una forma integrada de evitar estas colisiones. Tal vez esto suceda en el futuro. Para aplicaciones grandes donde este problema es más probable, tienes razón en que las convenciones de nombres son tu mejor herramienta. Considere si los objetos que pertenecen a un módulo o área de función pueden usar un prefijo corto.
Defina sus controladores en el módulo desde el que quiere que sea el servicio.
service2Module.controller("ServiceTwoCtrl", function(myService, $scope) {});
Desafortunadamente, no hay namespacing
para namespacing
en AngularJS . Una solución es usar un prefix
(¡otra solución puede ser this !). Vea el siguiente ejemplo:
// root app
const rootApp = angular.module(''root-app'', [''app1'', ''app2'']);
// app 1
const app1 = angular.module(''app1'', []);
app1.controller(''app1.main'', function($scope) {
$scope.msg = ''App1'';
});
// app2
const app2 = angular.module(''app2'', []);
app1.controller(''app2.main'', function($scope) {
$scope.msg = ''App2'';
})
<!-- [email protected] -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.0/angular.min.js"></script>
<!-- root app -->
<div ng-app="root-app">
<!-- app 1 -->
<div ng-controller="app1.main">
{{msg}}
</div>
<!-- app 2 -->
<div ng-controller="app2.main">
{{msg}}
</div>
</div>
Puede evitar esta situación utilizando una convención para nombrar sus módulos para que sean siempre únicos.
Un enfoque es observar cómo lo hacen otros idiomas. Por ejemplo, en Java, el "nombre completo" de la clase se basa en el nombre del archivo y la carpeta en la que se encuentra. Por ejemplo, si tuviera un archivo Java llamado Bitmap.java en la carpeta MyArtStuff, el nombre completo de la clase be MyArtStuff.Bitmap
Resulta que AngularJS le permite tener puntos (.) Como parte del nombre de su módulo, por lo que esencialmente podría usar la convención de nombres.
Por ejemplo, si un desarrollador crea un módulo llamado "ModuleA" en la secuencia de comandos "MainPage / Module1.js", debe nombrar a su módulo "MainPage.Module1.ModuleA". Debido a que cada ruta y nombre de archivo es único en su aplicación, entonces el nombre de su módulo será único.
Solo deberías hacer que tus desarrolladores sigan esta convención.
Tenga en cuenta que Rockallite señala que esto no ayudará con los servicios, controladores, etc. que tengan el mismo nombre en varios módulos. Pero puede usar un enfoque similar para dar como resultado y prefijar los nombres de esos elementos también.
Idealmente, AngularJS tendría espacios de nombres y en el futuro podría tenerlos. Hasta entonces, lo mejor que podemos hacer es hacer lo que los desarrolladores han estado haciendo durante más de 40 años antes de que se inventaran los espacios de nombres y prefijar lo mejor posible nuestros elementos.