it-swarm.com.de

Wie kann geprüft werden, ob ein Modul vorhanden ist, ohne dass ein Fehler aufgetreten ist?

In Angular 1.2 ist ngRoute ein separates Modul, sodass Sie stattdessen andere Community-Router wie ui.router verwenden können.

Ich schreibe ein Open-Source-Modul, das für mehrere verschiedene Router-Implementierungen geeignet ist. Wie kann ich also überprüfen, welcher Router geladen ist oder existiert?

Ich mache folgendes in einer Fabrik in meinem Modul, aber es funktioniert nicht so, wie ich es erwartet habe:

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

Es wird ein Fehler für das Modul ausgelöst, das nicht geladen ist. Wenn die App beispielsweise ui.router verwendet, wird der folgende Fehler für die ngRoute-Prüfung ausgelöst:

Nicht abgerufener Fehler: [$ injector: nomod] Das Modul 'ngRoute' ist nicht verfügbar! Sie haben entweder den Modulnamen falsch geschrieben oder das Laden vergessen. Ob Wenn Sie ein Modul registrieren, stellen Sie sicher, dass Sie die Abhängigkeiten als .__ angeben. zweites Argument.

41

Mir ist keine Möglichkeit bekannt, zu prüfen, ohne dass ein Fehler auftritt. Beachten Sie jedoch, dass das Problem darin besteht, dass es sich um einen Uncaught Error handelt, nicht um einen Fehler. Das Muster zum Erkennen eines solchen Fehlers ist das folgende.

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

Wenn ein Fehler aufgetreten ist, können Sie das andere Modul ausprobieren. Wenn nicht, können Sie das erste Modul verwenden.

Wenn Ihr Verhalten für jedes Modul gleich ist, können Sie etwa Folgendes tun, indem wir eine Funktion definieren, die den ersten der aufgelisteten Modulnamen versucht. Wenn ein Fehler ausgegeben wird, versuchen Sie die nächste Option.

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

Ich würde den Dienst anstelle des Moduls selbst testen.

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

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

}

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

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

}
9
d3l33t

Die ursprüngliche Antwort ist echt. Als Alternative schrieb ich dies, wenn ich die Module "finden oder erstellen" musste. Es gibt eine Reihe von Anwendungsfällen, aber im Allgemeinen müssen Sie sich nicht um die Reihenfolge beim Laden von Dateien kümmern. Sie können dies entweder in einen initialModules.js... setzen oder der Anfang aller Ihrer individuellen Service-/Direktive-Dateien beginnt mit etwas Ähnlichem. Diese kleine Funktion wirkt für mich wie ein Zauber:

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

Wenn Sie angular.module Dekorieren, um die Namen in einem Array zu speichern, können Sie einfach überprüfen, ob das Array Ihren Modulnamen enthält.

Winkelmodul dekorieren

Siehe @ dsfqs Antwort auf SO .

Dies muss geschehen, nachdem angular geladen wurde, aber bevor Sie mit dem Laden von angular - Modulen beginnen.

Überprüfen Sie für Ihr Modul

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

1
Scotty.NET

Eine viel bessere Lösung ist, einfach zu prüfen, wann das Modul erstellt wird. Sie benötigen lediglich eine Utility-Funktion, um einen Rückruf hinzuzufügen.

//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 und höher hat eine Möglichkeit, um zu prüfen, ob ein Modul geladen ist über den $ injector-Dienst.

In 1.6.7 wurde außerdem die Fähigkeit zum Laden neuer Module hinzugefügt, die für einige von Interesse sein kann.

0
jazd

Das Problem, ein Modul automatisch zu laden oder zu erstellen, könnte jedoch durch so etwas wie gulp-angle-filesort besser gelöst werden. Es funktioniert wirklich einwandfrei.

Auf der gulp-angle-filesort github-Seite: AngularJS-App-Dateien automatisch nach Moduldefinitionen und Verwendung sortieren

Wird in Verbindung mit gulp-inject verwendet, um Ihre AngularJS-Anwendungsdateien (Skripts) in der richtigen Reihenfolge einzufügen, um alle Uncught Error: [$ injector: modulerr] zu entfernen.

Disclaimer: Ich bin nicht mit gulp-angle-filesort verbunden, ich verwende es nur mit großem Gewinn.

0
ivan.saorin