Как проверить наличие модуля без возникновения ошибки?
В 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
проверять:
Uncaught Error: [$ инжектор:nomod] Модуль 'ngRoute' недоступен! Вы либо неправильно написали имя модуля, либо забыли загрузить его. При регистрации модуля убедитесь, что вы указали зависимости в качестве второго аргумента.
7 ответов
Я не знаю способ проверки без возникновения ошибки; Тем не менее, обратите внимание, что проблема в том, что это было 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"]);
Я бы протестировал сервис вместо самого модуля.
// In controller
if($injector.has('$route')){
}
if($injector.has('$state')){
}
// In angular config
if($injector.has('$routeProvider')){
}
if($injector.has('$stateProvider')){
}
Оригинальный ответ является законным. Однако, в качестве альтернативы, я написал это, когда мне нужно было "найти или создать" модули. Существует несколько вариантов использования, но, как правило, это позволяет вам не беспокоиться о порядке загрузки файлов. Вы можете поместить это в 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);
Если вы украшаете angular.module
чтобы сохранить имена в массиве, вы можете просто проверить, содержит ли массив имя вашего модуля.
Украсить angular.module
Смотрите ответ @dsfq на SO.
Это должно произойти после загрузки угловых модулей, но перед началом загрузки любых угловых модулей.
Проверьте свой модуль
if(angular.modules.indexOf("ngRoute") > -1) ...
Гораздо лучшим решением будет просто выполнить проверку при создании модуля. Вам просто нужна служебная функция для добавления обратного вызова.
//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
}
});
Однако проблема автоматической загрузки или создания модуля может быть лучше решена с помощью gulp-angular-filesort. Это работает действительно безупречно.
Со страницы github https://github.com/klei/gulp-angular-filesort:Автоматическая сортировка файлов приложения AngularJS в зависимости от определений модуля и использования
Используется вместе с gulp-inject для внедрения файлов приложения (скриптов) AngularJS в правильном порядке, чтобы избавиться от всех Uncaught Error: [$ injector: modulerr].
Отказ от ответственности: я не связан с gulp-angular-filesort, я использую его только с большой прибылью.
AngularJS 1.6.3 и выше имеет возможность проверить, загружен ли модуль через сервис $ инжектор.
Также в 1.6.7 была добавлена возможность загружать новые модули, которые могут быть интересны для некоторых.