在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'不可用! 您要么错误拼写了模块名称,要么忘记加载它。如果 注册模块确保您将依赖项指定为 第二个论点。
答案 0 :(得分:55)
我不知道在没有错误的情况下进行检查的方法;但是,请注意问题是它是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"]);
答案 1 :(得分:9)
我会测试服务而不是模块本身。
// In controller
if($injector.has('$route')){
}
if($injector.has('$state')){
}
// In angular config
if($injector.has('$routeProvider')){
}
if($injector.has('$stateProvider')){
}
答案 2 :(得分:6)
原来的答案是合法的。但是,作为替代方案,当我需要“查找或创建”模块时,我写了这个。有许多用例,但一般来说,它让您不必担心文件加载顺序。您可以将其放在initialModules.js
...或者所有单个服务/指令文件的顶部以这样的内容开头。这个小功能对我来说就像一个魅力:
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);
答案 3 :(得分:1)
如果您装饰angular.module
以将名称存储在数组中,那么您只需检查数组是否包含模块名称。
这需要在加载角度之后但在开始加载任何角度模块之前发生。
if(angular.modules.indexOf("ngRoute") > -1) ...
答案 4 :(得分:0)
自动加载或创建模块的问题可以通过诸如gulp-angular-filesort之类的东西更好地解决。 它的工作非常完美。
来自gulp-angular-filesort github页面: 根据模块定义和用法自动对AngularJS应用程序文件进行排序
与gulp-inject结合使用,以正确的顺序注入AngularJS应用程序文件(脚本),以消除所有 Uncaught Error:[$ injector:modulerr] 。
免责声明:我与gulp-angular-filesort没有任何关系,我只是以大量利润使用它。
答案 5 :(得分:0)
更好的解决方案是在创建模块时简单地进行检查。您只需要一个实用程序函数来添加回调。
//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
}
});
答案 6 :(得分:0)
AngularJS 1.6.3及更高版本通过$ injector服务获得a way to check if a module is loaded。
1.6.7中还添加了ability to load new modules,这可能是某些人感兴趣的。