it-swarm.com.ru

Как проверить наличие модуля без возникновения ошибки?

В 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' недоступен! Вы либо неправильно написали имя модуля, либо забыли загрузить его. Если при регистрации модуля убедитесь, что вы указали зависимости как Второй аргумент.

41
XåpplI'-I0llwlg'I -

Я не знаю способ проверки без возникновения ошибки; однако обратите внимание, что проблема в том, что это был 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"]);
55
matt3141

Я бы протестировал сервис вместо самого модуля.

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

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

}

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

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

}
9
d3l33t

Оригинальный ответ является законным. Однако, в качестве альтернативы, я написал это, когда мне нужно было «найти или создать» модули. Существует несколько вариантов использования, но, как правило, это позволяет вам не беспокоиться о порядке загрузки файлов. Вы можете либо поместить это в 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);
6
bwest87

Если вы декорируете angular.module для хранения имен в массиве, вы можете просто проверить, содержит ли массив имя вашего модуля.

Украсить angular.module

Смотрите @ dsfq ответ на SO .

Это должно произойти после загрузки угловых модулей, но перед началом загрузки любых угловых модулей.

Проверьте свой модуль

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

1
Scotty.NET

Гораздо лучшим решением будет просто выполнить проверку при создании модуля. Вам просто нужна служебная функция для добавления обратного вызова.

//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 и выше имеет способ проверить, загружен ли модуль через сервис $ инжектор.

Также в 1.6.7 была добавлена ​​ возможность загружать новые модули которые могут быть интересны для некоторых.

0
jazd

Проблема автоматической загрузки или создания модуля может быть лучше решена с помощью чего-то вроде gulp-angular-filesort, хотя .. Это работает действительно безупречно.

From gulp-angular-filesort github page: Автоматически сортировать файлы приложения AngularJS в зависимости от определений модуля и использования

Используется вместе с gulp-inject для внедрения файлов приложений (скриптов) AngularJS в правильном порядке, чтобы избавиться от всех Uncaught Error: [$ injector: modulerr].

Disclaimer: я не связан с gulp-angular-filesort, я использую его только с большой прибылью.

0
ivan.saorin