如何检查模块是否存在,而不会引发错误?

在Angular 1.2中, ngRoute是一个独立的模块,所以你可以使用其他社区路由器,比如ui.router

我正在编写一个开放源代码模块,旨在为多个不同的路由器实现工作。 那么如何检查哪个路由器被加载或存在?

我在我的模块中的一个工厂内部正在做以下工作,但它不按照我所期望的方式工作:

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

它会引发一个错误,无论哪个模块没有加载。 例如,如果应用程序使用的是ui.router ,那么ngRoute检查会引发以下错误:

未捕获的错误:[$ injector:nomod]模块'ngRoute'不可用! 您拼写错误的模块名称或忘记加载它。 如果注册一个模块,确保你指定依赖关系作为第二个参数。

我不知道有没有提出错误检查的方式; 但是,请注意,问题是这是一个Uncaught Error ,而不是一个错误被抛出。 捕捉这种错误的模式如下。

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

如果发现错误,您可以尝试其他模块,如果没有,您可以使用第一个。

如果你的行为对于每个模块都是一样的,你可以做如下的事情,在这个行为中我们定义了一个函数,它会尝试列出第一个模块名,如果有错误发生,请尝试下一个选项。

 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"]); 

我会testing服务而不是模块本身。

 // In controller if($injector.has('$route')){ } if($injector.has('$state')){ } // In angular config if($injector.has('$routeProvider')){ } if($injector.has('$stateProvider')){ } 

原来的答案是合法的。 但是,作为替代scheme,当我需要“查找或创build”模块时,我写了这个。 有很多用例,但通常它可以让您不必担心文件加载顺序。 你可以把它放在一个initialModules.js ,或者你所有的个人服务/指令文件的开头都是这样的。 这个小function对我来说就像是一种魅力:

 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); 

如果你装饰angular.module来存储数组中的名字,那么你可以检查数组是否包含你的模块名称。

装饰angular.module

查看@ dsfq在SO上的答案 。

这需要在加载angular度之后但在开始加载任何angular度模块之前进行。

检查你的模块

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

但是,自动加载或创build模块的问题可以通过像gulp-angular-filesort这样的东西来解决。 它的工作非常完美。

从gulp-angular-filesort github页面: 根据模块定义和用法自动分类AngularJS应用程序文件

与gulp-inject一起使用,以正确的顺序注入您的AngularJS应用程序文件(脚本),摆脱所有未捕获的错误:[$ injector:modulerr]

免责声明 :我不隶​​属于gulp-angular-filesort,我只是用它获得了很多利润。

更好的解决scheme是在创build模块时简单地进行检查。 你只需要一个实用的function来添加一个callback。

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