Comment vérifier l’existence d’un module sans qu’une erreur soit générée?

Dans Angular 1.2, ngRoute est un module distinct, vous pouvez donc utiliser d’autres routeurs communautaires tels que ui.router .

J’écris un module open-source qui a pour but de travailler avec plusieurs implémentations de routeurs. 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 je l’espère:

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

Cela génère une erreur pour n’importe quel module non chargé. Par exemple, si l’application utilise ui.router , l’erreur suivante est ngRoute pour la vérification ngRoute :

Erreur non détectée: [$ injector: nomod] Le module ‘ngRoute’ n’est pas disponible! Vous avez soit mal orthographié le nom du module, soit oublié de le charger. Si vous enregistrez un module, assurez-vous de spécifier les dépendances comme deuxième argument.

Je ne suis pas au courant d’une manière de vérifier sans qu’une erreur soit soulevée; Toutefois, notez que le problème est qu’il s’agissait d’une Uncaught Error non Uncaught Error et non d’une erreur. Le schéma de capture d’une telle erreur est le suivant.

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

Si une erreur est détectée, vous pouvez essayer l’autre module, sinon vous pouvez utiliser le premier.

Si votre comportement est le même pour chaque module, vous pouvez faire quelque chose comme ce qui suit, dans lequel nous définissons une fonction qui tentera le premier des noms de module listés, et si une erreur est lancé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"]); 

Je testerais 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')){ } 

La réponse originale est légitime. Cependant, comme alternative, j’ai écrit ceci quand j’avais besoin de “trouver ou créer” les modules. Il y a un certain nombre de cas d’utilisation, mais en général, cela ne vous oblige pas à vous soucier de l’ordre de chargement des fichiers. Vous pouvez soit mettre ceci dans un initialModules.js … ou le haut de tous vos fichiers de service / directive individuels commencent par quelque chose comme ça. 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); 

Si vous décorez angular.module pour stocker les noms dans un tableau, vous pouvez simplement vérifier si le tableau contient le nom de votre module.

Décorez le module angular

Voir la réponse de @dsfq sur SO .

Cela doit se produire après le chargement angular mais avant de commencer à charger des modules angulars.

Vérifiez votre module

if(angular.modules.indexOf("ngRoute") > -1) ...

Le problème du chargement automatique ou de la création d’un module pourrait être mieux résolu avec quelque chose comme gulp-angular-filesort. Cela fonctionne vraiment parfaitement.

De la page github gulp-angular-filesort : Tri automatique des fichiers d’application AngularJS en fonction des définitions et de l’utilisation des modules

Utilisé en conjonction avec gulp-inject pour injecter vos fichiers d’application (scripts) AngularJS dans un ordre correct, pour se débarrasser de toutes les erreurs non détectées: [$ injector: modulerr] .

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

Une solution bien meilleure consiste à faire simplement votre vérification lorsque le module est créé. Vous avez juste besoin d’une fonction utilitaire pour append 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 } }); 

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

La possibilité de charger de nouveaux modules pouvant intéresser certains utilisateurs a également été ajoutée au 1.6.7.