web-dev-qa-db-fra.com

Comment vérifier l'existence d'un module sans générer d'erreur?

Dans Angular 1.2, ngRoute est un module séparé qui vous permet d'utiliser d'autres routeurs de communauté tels que ui.router.

J'écris un module open-source qui vise à fonctionner pour plusieurs implémentations de routeurs différentes. Alors, comment puis-je vérifier quel routeur est chargé ou existe?

Je fais ce qui suit à l'intérieur d'une usine dans mon module, mais cela ne fonctionne pas comme prévu:

if (angular.module("ngRoute"))
  // Do ngRoute-specific stuff.
else if (angular.module("ui.router"))
  // Do ui.router-specific stuff.

Une erreur est générée pour le module non chargé. Par exemple, si l'application utilise ui.router, l'erreur suivante est générée pour la vérification ngRoute:

Erreur non capturée: [$ injector: nomod] Le module 'ngRoute' n'est pas disponible! Vous avez mal orthographié le nom du module ou vous avez oublié de le charger. Si en enregistrant un module, assurez-vous de spécifier les dépendances en tant que deuxième argument.

41

Je ne suis pas au courant d'un moyen de vérifier sans qu'une erreur soit générée; Cependant, notez que le problème est qu’il s’agissait d’un Uncaught Error et non qu’une erreur avait été générée. Le modèle permettant de détecter une telle erreur est le suivant.

try { angular.module("ngRoute") } catch(err) { /* failed to require */ }

Si une erreur est interceptée, vous pouvez essayer l'autre module et sinon, vous pouvez utiliser le premier.

Si votre comportement est identique pour chaque module, vous pouvez utiliser la procédure suivante, dans laquelle nous définissons une fonction qui tentera le premier des noms de modules répertoriés. Si une erreur est générée, essayez l'option suivante.

var tryModules = function(names) {
  // accepts a list of module names and
  // attempts to load them, in order.

  // if no options remain, throw an error.
  if( names.length == 0 ) {
    throw new Error("None of the modules could be loaded.");
  }

  // attempt to load the module into m
  var m;
  try {
    m = angular.module(names[0])
  } catch(err) {
    m = null;
  }

  // if it could not be loaded, try the rest of
  // the options. if it was, return it.
  if( m == null ) return tryModules(names.slice(1));
  else return m;
};

tryModules(["ngRoute", "ui.router"]);
55
matt3141

Je voudrais tester le service au lieu du module lui-même.

// In controller
if($injector.has('$route')){

}
if($injector.has('$state')){

}

// In angular config
if($injector.has('$routeProvider')){

}
if($injector.has('$stateProvider')){

}
9
d3l33t

La réponse originale est légitime. Cependant, au lieu de cela, j’ai écrit ceci lorsque j’avais besoin de "trouver ou de créer" les modules. Il existe un certain nombre de cas d'utilisation, mais en général, cela vous évite d'avoir à vous soucier de l'ordre de chargement des fichiers. Vous pouvez soit mettre ceci dans un initialModules.js... ou au sommet de tous vos fichiers de service/directive individuels commencent par quelque chose comme ceci. Cette petite fonction fonctionne comme un charme pour moi:

var initialModules = [
  {name: 'app.directives', deps: ['ui.mask']},
  {name: 'app.services'},
  {name: 'app.templates'},
  {name: 'app.controllers'}
];

initialModules.forEach(function(moduleDefinition) {
  findOrCreateModule(moduleDefinition.name, moduleDefinition.deps);
});

function findOrCreateModule(moduleName, deps) {
  deps = deps || [];
  try {
    angular.module(moduleName);
  } catch (error) {
    angular.module(moduleName, deps);
  }
}


///// OR... in like "myDirective.js"
findOrCreateModule('app.directives').directive('myDirective', myDirectiveFunction);
6
bwest87

Une solution bien meilleure consiste simplement à faire votre vérification lorsque le module est créé. Vous avez juste besoin d'une fonction utilitaire pour ajouter un rappel.

//create a utility function to add a callback to object methods    
//here we are making it a method of the underscore or lowdash object
//but it could be added to the angular global object or anything else
_.addCallBack = function (obj, originalMethodName, callBackMethod, context){
            var fnOriginal = obj[originalMethodName],
                outcome;

            context = context || obj;

            obj[originalMethodName] = function () {
                var outcome = fnOriginal.apply(this, arguments);

                callBackMethod.apply(this, arguments);

                return outcome;
            };
};

_.addCallBack(angular, "module", function(sModuleName, asDependencies){
    if(_.contains(asDependencies, "ngRoute")){
      //your logic here
      //just loop through if you don't use underscore or lowdash
    }
});
0
cage rattler

AngularJS 1.6.3 et versions ultérieures ont un moyen de vérifier si un module est chargé via le service $ injector.

La version {1.6.7 a également été ajoutée à la possibilité de charger de nouveaux modules qui pourrait intéresser certains.

0
jazd

Le problème du chargement automatique ou de la création d'un module pourrait être mieux résolu par quelque chose comme gulp-angular-filesort, cependant .. Cela fonctionne vraiment sans faille.

De gulp-angular-filesort github page: Tri automatique des fichiers de l'application AngularJS en fonction des définitions et de l'utilisation du module

Utilisé conjointement avec gulp-inject pour injecter les fichiers de votre application AngularJS (scripts) dans un ordre correct, afin de supprimer tous les Uncaught Error: [$ injector: modulerr].

Disclaimer: Je ne suis pas affilié à gulp-angular-filesort, je l'utilise seulement avec beaucoup de profit.

0
ivan.saorin