Modules et namespace / nom collision en AngularJS

Considérez les points suivants 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");
}​

j'ai 2 modules (module1 et module2). Module1 et module2 définissent un service appelé myService. Cela semble créer un conflit de nom sur myService dans Angular lorsque les deux modules sont importés dans myApp. Il semble AngularJs utilise juste la deuxième définition de service sans vous avertir du problème.

très les grands projets (ou la simple réutilisation de modules en général) risqueraient d'avoir des noms qui s'entrechoquent, ce qui pourrait être difficile à déboguer.

est-ce qu'il y a un moyen de préfixer les noms avec le nom du module pour éviter les conflits de noms?

48
demandé sur Gajanan Kulkarni 2012-11-16 01:46:18

4 réponses

A partir d'aujourd'hui, les modules AngularJS ne fournissent aucune sorte d'Espace-nom qui empêcherait les collisions entre objets dans différents modules. La raison est qu'une application AngularJS a un injecteur simple qui détient des noms pour tous les objets sans respect pour les noms de module.

Le AngularJS Guide du Développeur dit:

pour gérer la responsabilité de la création de dépendances, chaque angle l'application dispose d'une injecteurs. L'injecteur est un localisateur de service est responsable de la construction et de la recherche des dépendances.

comme vous l'avez mentionné, des bogues désagréables peuvent survenir lors de l'injection de modules dans votre module principal/app. Lorsque des collisions se produisent, ils sont silencieux et le gagnant est déterminé par celui qui a été le dernier module injecté.

donc non, il n'y a pas de moyen d'éviter ces collisions. Peut-être ce qui va se passer dans l'avenir. Pour les grands applications où ce problème devient plus probable, vous avez raison que les conventions de nommage sont votre meilleur outil. Examinez si les objets appartenant à un module ou à une zone de fonction peuvent utiliser un préfixe court.

61
répondu Jim Ierley 2013-11-26 18:39:45

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. Par exemple en Java, le "nom complet" de la classe est basée sur le nom du fichier et le dossier. Par exemple, si vous aviez un fichier Java appelé Bitmap.java dans le dossier MyArtStuff, le nom complet de la classe serait MyArtStuff.Bitmap

S'avère AngularJS vous permet de ont des points (.) dans le cadre de votre nom de module afin que vous puissiez essentiellement utiliser la convention name.

par exemple si un développeur crée un module appelé" ModuleA "dans le script" MainPage\Module1.js" ils doivent le nom de leur module "de la page d'accueil.Module1.ModuleA". Comme chaque chemin et chaque nom de fichier est unique dans votre application, le nom de votre module sera unique.

vous auriez juste à amener vos développeurs à suivre cette convention.

Note as Rockallite souligne que cela n'aidera pas avec les services, contrôleurs, ETC ayant le même nom dans plusieurs modules. Mais vous pouvez utiliser une approche similaire pour le résultat et préfixer les noms de ces éléments ainsi.

idéalement AngularJS aurait des espaces de noms et dans le futur il pourrait. D'ici là, le mieux que nous puissions faire est de faire ce que les développeurs ont fait pendant plus de 40 ans avant l'invention des namespaces et de préfixer nos éléments du mieux que nous pouvons.

2
répondu Luis Perez 2015-06-29 02:00:52

malheureusement, il n'y a pas de namespacing dans AngularJS . Une solution est d'utiliser un prefix (une autre solution peut être ce !). 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';
})
<!-- angularjs@1.7.0 -->
<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>
0
répondu Yas 2018-06-08 06:00:45

Définissez vos contrôleurs sur le module d'où vous voulez que le service soit.

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

-8
répondu Andrew Joslin 2012-11-16 00:00:45