Collision des modules et des espaces de noms / noms dans AngularJS

Considérez le jfiddle suivant 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"); }​ 

J’ai 2 modules (module1 et module2). Module1 et module2 définissent tous deux un service appelé myService. Cela semble créer un conflit de noms sur myService dans Angular lorsque les deux modules sont importés dans myApp. Il semble qu’AngularJs utilise simplement la définition du second service sans vous avertir du problème possible.

De très gros projets (ou simplement la réutilisation de modules en général) risqueraient de se heurter à des noms, ce qui pourrait être difficile à déboguer.

Y a-t-il un moyen de préfixer les noms avec le nom du module afin que les conflits de noms ne se produisent pas?

À ce jour, les modules AngularJS ne fournissent aucune sorte d’espaces de noms permettant d’éviter les collisions entre les objects des différents modules. La raison en est qu’une application AngularJS possède un seul injecteur qui contient les noms de tous les objects sans respecter les noms de module.

Le Guide du développeur AngularJS dit:

Pour gérer la responsabilité de la création de dépendances, chaque application angular possède un injecteur. L’injecteur est un localisateur de services responsable de la construction et de la recherche des dépendances.

Comme vous l’avez mentionné, des erreurs peuvent survenir lors de l’injection de modules dans votre module principal / app. Lorsque des collisions se produisent, elles sont silencieuses et le gagnant est déterminé par le dernier module injecté.

Donc non, il n’y a pas de moyen intégré pour éviter ces collisions. Peut-être que cela arrivera dans le futur. Pour les grandes applications où ce problème devient plus probable, vous avez raison: les conventions de nommage sont votre meilleur outil. Déterminez si les objects appartenant à un module ou à une zone de fonction peuvent utiliser un préfixe court.

Vous pouvez éviter cette situation en utilisant une convention pour nommer vos modules afin qu’ils soient toujours uniques.

Une approche consiste à regarder comment les autres langues le font. Par exemple, en Java, le «nom complet» de la classe est basé sur le nom du fichier et le dossier dans lequel il se trouve. Par exemple, si vous aviez un fichier Java appelé Bitmap.java dans le dossier MyArtStuff, le nom complet de la classe serait être MyArtStuff.Bitmap

AngularJS vous permet d’avoir des points (.) Dans le nom de votre module, vous pouvez donc essentiellement utiliser la convention de nom.

Par exemple, si un développeur crée un module appelé «ModuleA» dans le script «MainPage \ Module1.js», il doit nommer son module «MainPage.Module1.ModuleA». Chaque chemin et nom de fichier étant unique dans votre application, le nom de votre module sera unique.

Il suffirait que vos développeurs suivent cette convention.

Notez que Rockallite souligne que cela ne va pas aider avec les services, les contrôleurs, etc. ayant le même nom dans plusieurs modules. Mais vous pouvez utiliser une approche similaire pour obtenir un résultat qui préfixe également les noms de ces éléments.

Idéalement, AngularJS aurait des espaces de noms et dans le futur, il pourrait l’être. Jusque-là, le mieux que nous puissions faire est de faire ce que les développeurs font depuis plus de 40 ans avant que les espaces de noms aient été inventés et préfixés au mieux nos éléments.

Malheureusement, il n’y a pas d’ namespacing de namespacing dans AngularJS . Une solution consiste à utiliser un prefix (une autre solution peut être celle-ci !). Voir l’exemple suivant:

 // 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'; }) 
    
{{msg}}
{{msg}}

Définissez vos contrôleurs sur le module dont vous souhaitez que le service soit.

service2Module.controller("ServiceTwoCtrl", function(myService, $scope) {});